1+ #![ allow( non_snake_case) ]
2+ use std:: thread;
3+ use std:: env;
4+ use std:: process:: Command ;
5+ use std:: sync:: mpsc:: SyncSender ;
6+ use std:: sync:: mpsc:: sync_channel;
7+ use std:: fs:: File ;
8+ use std:: io:: prelude:: * ;
9+ use std:: time:: Instant ;
10+
11+ const maxThreads: i8 = 8 ;
12+
13+ struct CompleteTask {
14+ startNode : i16 ,
15+ paths : Vec < Vec < i16 > > ,
16+ }
17+
18+ fn main ( ) {
19+ let mut _totalNodes: String = "0" . to_string ( ) ;
20+ for argument in env:: args ( ) {
21+ _totalNodes = argument. to_string ( ) ;
22+ }
23+ println ! ( "You have chosen to order numbers upto {}" , _totalNodes) ;
24+ let totalNodes: i16 = _totalNodes. parse :: < i16 > ( ) . unwrap ( ) ;
25+ let now = Instant :: now ( ) ;
26+
27+ let paths = getCore ( totalNodes, now) ;
28+
29+ let endTime = now. elapsed ( ) . as_secs ( ) ;
30+ printResult ( paths, totalNodes) ;
31+ println ! ( "It took aproximately {} seconds to compute" , endTime) ;
32+ }
33+
34+ fn getCore ( totalNodes : i16 , now : Instant ) -> Vec < Vec < i16 > > {
35+ let connections: Vec < [ i16 ; 2 ] > = findConnections ( totalNodes) ;
36+ let ( sender, reciever) = sync_channel ( maxThreads as usize ) ;
37+ let mut paths: Vec < Vec < i16 > > = vec ! [ ] ;
38+
39+ println ! ( "There are {} connections" , connections. len( ) ) ;
40+
41+ let mut i: i16 = 0 ;
42+ let mut openThreads = 0 ;
43+ loop {
44+ while ( openThreads < maxThreads as usize ) && ( i < totalNodes) {
45+ startCalcAsync ( i, connections. clone ( ) , totalNodes. clone ( ) , sender. clone ( ) ) ;
46+ openThreads += 1 ;
47+ i += 1 ;
48+ }
49+
50+ let completedTask = reciever. recv ( ) . unwrap ( ) ;
51+ paths. append ( & mut completedTask. paths . clone ( ) ) ;
52+ openThreads -= 1 ;
53+
54+ println ! ( "finnished task {} of {} at {} seconds" , completedTask. startNode, totalNodes, now. elapsed( ) . as_secs( ) ) ;
55+
56+ if openThreads == 0 {
57+ break ;
58+ }
59+ }
60+ return paths;
61+ }
62+
63+ fn startCalcAsync ( startNode : i16 , connections : Vec < [ i16 ; 2 ] > , totalNodes : i16 , sender : SyncSender < CompleteTask > ) {
64+ println ! ( "Starting task {}" , startNode) ;
65+
66+ let mut path: Vec < i16 > = Vec :: with_capacity ( totalNodes as usize ) ;
67+ path. push ( startNode) ;
68+
69+ thread:: spawn ( move || {
70+ let paths = doThread ( connections, path, totalNodes) ;
71+ sender. send ( CompleteTask {
72+ startNode : startNode,
73+ paths : paths,
74+ } ) . unwrap ( ) ;
75+ } ) ;
76+ }
77+ fn printResult ( paths : Vec < Vec < i16 > > , totalNodes : i16 ) {
78+ println ! ( "Exporting final data..." ) ;
79+ let result = File :: create ( "Output.txt" ) ;
80+ let mut file: File = match result {
81+ Ok ( x) => x,
82+ Err ( e) => {
83+ println ! ( "Error on Output Attempt: {}" , e) ;
84+ return ;
85+ } ,
86+ } ;
87+ let mut completePaths: i16 = 0 ;
88+ for path in paths. clone ( ) {
89+ if path. len ( ) == totalNodes as usize {
90+ write ! ( file, "A working path is " ) ;
91+ completePaths += 1 ;
92+ for node in path {
93+ write ! ( file, "{} " , node) ;
94+ }
95+ write ! ( file, "\n " ) ;
96+ }
97+ }
98+
99+ println ! ( "DONE!" ) ;
100+ println ! ( "Completed with {} paths" , paths. len( ) ) ;
101+ println ! ( "{} of them are complete paths" , completePaths) ;
102+ println ! ( "All working paths have been outputted to Output.txt" ) ;
103+ }
104+
105+ fn doThread ( connections : Vec < [ i16 ; 2 ] > , _path : Vec < i16 > , totalNodes : i16 ) -> Vec < Vec < i16 > > {
106+ let mut path = _path. clone ( ) ;
107+ let mut paths: Vec < Vec < i16 > > = Vec :: with_capacity ( totalNodes as usize ) ;
108+
109+ loop {
110+ let node = path[ path. len ( ) -1 ] ;
111+ let mut goTo: i16 = 0 ;
112+ let mut isFirstConnection: bool = true ;
113+ for connection in connections. clone ( ) {
114+ let mut connectedTo: i16 = 0 ;
115+ if node == connection[ 0 ] {
116+ connectedTo = connection[ 1 ] ;
117+ } else if node == connection[ 1 ] {
118+ connectedTo = connection[ 0 ] ;
119+ } else {
120+ continue ;
121+ }
122+
123+ if !isNodeInPath ( connectedTo, path. clone ( ) ) {
124+ if isFirstConnection {
125+ isFirstConnection = false ;
126+ goTo = connectedTo;
127+ } else {
128+ let mut newPath = path. clone ( ) ;
129+ newPath. push ( connectedTo) ;
130+ let newConnections = connections. clone ( ) ;
131+ paths. append ( & mut doThread ( newConnections, newPath, totalNodes) ) ;
132+ }
133+ }
134+ }
135+ if isFirstConnection {
136+ break ;
137+ } else {
138+ path. push ( goTo) ;
139+ }
140+ }
141+
142+ paths. push ( path) ;
143+ return paths;
144+ }
145+
146+ fn isNodeInPath ( node : i16 , path : Vec < i16 > ) ->bool {
147+ for nodeToCheck in path {
148+ if nodeToCheck == node {
149+ return true ;
150+ }
151+ }
152+ return false ;
153+ }
154+
155+ fn findConnections ( totalNodes : i16 ) -> Vec < [ i16 ; 2 ] > {
156+ let mut connections: Vec < [ i16 ; 2 ] > = vec ! [ ] ;
157+ for i in 1 ..totalNodes {
158+ for j in i+1 ..totalNodes+1 {
159+ if isSquare ( i+j) {
160+ connections. push ( [ i, j] ) ;
161+ }
162+ }
163+ }
164+ return connections;
165+ }
166+
167+ fn isSquare ( num : i16 ) -> bool {
168+ let sqrt: f64 = ( num as f64 ) . sqrt ( ) ;
169+ return sqrt == sqrt. round ( ) ;
170+ }
0 commit comments