33
|
1 {
|
|
2 _classifNode <- :vals prog startIdx child? {
|
|
3 if: startIdx < (vals length) {
|
|
4 _dict <- dict linear
|
|
5 _const <- #[]
|
|
6 _first <- false
|
|
7 _hasFirst? <- false
|
|
8 _val <- vals get: startIdx
|
|
9 #{
|
|
10 input <- { _val }
|
|
11 valmap <- { _dict }
|
38
|
12 allInputs <- { vals }
|
33
|
13 constantProgs <- { _const }
|
|
14 append <- :tree {
|
|
15 if: child? && (tree constant?) {
|
|
16 _const append: tree
|
|
17 } else: {
|
|
18 if: (_dict length) > 0 {
|
|
19 prog root!: tree
|
|
20 res <- prog run: _val
|
|
21 node <- _dict get: res elseSet: {
|
|
22 _classifNode: vals prog startIdx + 1 true
|
|
23 }
|
|
24 node append: tree
|
|
25 } else: {
|
|
26 if: _hasFirst? {
|
|
27 prog root!: _first
|
|
28 res <- prog run: _val
|
|
29 node <- _classifNode: vals prog startIdx + 1 true
|
|
30 _dict set: res node
|
|
31 node append: _first
|
|
32 append: tree
|
|
33 } else: {
|
|
34 _first <- tree
|
|
35 _hasFirst? <- true
|
|
36 }
|
|
37 }
|
|
38 }
|
|
39 }
|
|
40 length <- {
|
|
41 len <- _dict length
|
|
42 if: len = 0 && _hasFirst? {
|
|
43 len <- 1
|
|
44 }
|
38
|
45 len + (_const length)
|
33
|
46 }
|
|
47 printwithIndent <- :indent {
|
|
48 print: indent . "Input: " . (hex: _val) . "\n"
|
|
49 nextindent <- indent . " "
|
|
50 if: (_const length) > 0 {
|
|
51 print: indent . "Constants:\n"
|
|
52 foreach: _const :idx val {
|
|
53 print: nextindent . (string: val) . "\n"
|
|
54 }
|
|
55 }
|
|
56 if: (_dict length) > 0 {
|
|
57 foreach: _dict :key val {
|
|
58 print: indent . (hex: key) . " ->\n"
|
|
59 val printwithIndent: nextindent
|
|
60 }
|
|
61 } else: {
|
|
62 if: _hasFirst? {
|
|
63 print: nextindent . (string: _first) . "\n"
|
|
64 }
|
|
65 }
|
|
66 }
|
|
67 print <- {
|
|
68 printwithIndent: ""
|
|
69 }
|
38
|
70 findMatches:at <- :outputs :startIdx {
|
|
71 outVal <- outputs get: startIdx
|
|
72 sub <- _dict get: outVal withDefault: #{
|
|
73 length <- { 0 }
|
|
74 }
|
|
75 res <- #[]
|
|
76 if: (sub length) > 0 {
|
|
77 res <- sub findMatches: outputs at: (startIdx + 1)
|
|
78 cps <- sub constantProgs
|
|
79 if: (cps length) > 0 {
|
|
80 isConstant <- true
|
|
81 cur <- 0
|
|
82 while: { isConstant && cur < (cps length)} do: {
|
|
83 isConstant <- outVal = (outputs get: cur)
|
|
84 cur <- cur + 1
|
|
85 }
|
|
86 if: isConstant {
|
|
87 foreach: cps :idx tree {
|
|
88 res append: cps
|
|
89 }
|
|
90 }
|
|
91 }
|
|
92 }
|
|
93 res
|
|
94 }
|
33
|
95 }
|
|
96 } else: {
|
|
97 _arr <- #[]
|
|
98 #{
|
|
99 append <- :tree {
|
|
100 _arr append: tree
|
|
101 }
|
|
102 length <- { _arr length }
|
38
|
103 constantProgs <- { #[] }
|
33
|
104 printwithIndent <- :indent {
|
|
105 print: indent . "No more values for these:\n"
|
|
106 indent <- indent . " "
|
|
107 foreach: _arr :idx val {
|
|
108 print: indent . (string: val) . "\n"
|
|
109 }
|
|
110 }
|
|
111 print <- {
|
|
112 printwithIndent: ""
|
|
113 }
|
38
|
114 findMatches:at <- :outputs :startIdx {
|
|
115 _arr
|
|
116 }
|
32
|
117 }
|
|
118 }
|
|
119 }
|
33
|
120 #{
|
|
121 classify <- :prog trees numTests {
|
|
122 testvals <- #[]
|
|
123 i <- 0
|
|
124 (os srand: (os time))
|
|
125 while: {i < numTests} do: {
|
|
126 i <- i + 1
|
|
127 testvals append: (uint64: (os rand64))
|
|
128 }
|
|
129 root <- _classifNode: testvals prog 0 false
|
|
130 foreach: trees :idx tree {
|
|
131 root append: tree
|
|
132 }
|
|
133 root
|
32
|
134 }
|
33
|
135
|
38
|
136 solve:withAuth:andInfo:andProg <- :progId :authKey :info :prog {
|
|
137 resp <- (requests evalId: progId (info allInputs)) sendWithKey: authKey
|
|
138 if: (resp status) = "ok" {
|
|
139 matches <- info findMatches: (resp outputs) at: 0
|
|
140 noSuccess <- true
|
|
141 cur <- 0
|
|
142 while: { noSuccess && cur < (matches length) } do: {
|
|
143 prog root!: (matches get: cur)
|
|
144 gresp <- (requests guess: progId (string: prog)) sendWithKey: authKey
|
|
145 if: (gresp status) = "win" {
|
|
146 noSuccess <- false
|
|
147 } else: {
|
|
148 if: (gresp status) = "mismatch" {
|
|
149 failInput <- (gresp values) get: 0
|
|
150 failOutput <- (gresp values) get: 1
|
|
151 filtered <- #[]
|
|
152 foreach: matches :idx tree {
|
|
153 prog root!: tree
|
|
154 if: (prog run: failInput) = failOutput {
|
|
155 filtered append: tree
|
|
156 }
|
|
157 }
|
|
158 matches <- filtered
|
|
159 if: (matches length) = 0 {
|
|
160 print: "None of our programs actually matched 0x" . (hex: failOutput) ." with input 0x" . (hex: failInput) ." :(\n"
|
|
161 }
|
|
162 } else: {
|
|
163 print: "Got message: " . (gresp message) . ", moving on\n"
|
|
164 cur <- cur + 1
|
|
165 }
|
|
166 }
|
|
167 }
|
|
168 } else: {
|
|
169 print: resp
|
|
170 }
|
|
171 }
|
|
172
|
33
|
173 main <- :args {
|
|
174 size <- 3
|
|
175 if: (args length) > 1 {
|
|
176 size <- int32: (args get: 1)
|
32
|
177 }
|
33
|
178 prog <- bv program
|
|
179 if: size >= 2 {
|
|
180 trees <- (prog allOfSize: size)
|
|
181 numTests <- 0
|
|
182 if: (args length) > 2 {
|
|
183 numTests <- int32: (args get: 2)
|
|
184 }
|
|
185 if: numTests <= 0 {
|
|
186 numTests <- 16
|
|
187 }
|
|
188 if: (args length) > 3 {
|
|
189 ops <- (args get: 3) splitOn: ","
|
|
190 trees <- prog filterTrees: trees ops
|
|
191 }
|
|
192 info <- classify: prog trees numTests
|
38
|
193 if: (args length) > 5 {
|
|
194 progId <- (args get: 4)
|
|
195 authKey <- (args get: 5)
|
|
196
|
|
197 solve: progId withAuth: authKey andInfo: info andProg: prog
|
|
198 } else: {
|
|
199 print: info
|
|
200 }
|
32
|
201 }
|
38
|
202 0
|
32
|
203 }
|
|
204 }
|
|
205 }
|