on f3ca521 help sign in
140 lines 3.8 kB history raw
1+++
2title = "Bomb Defusing"
3weight = 7
4template = "doc.html"
5aliases = ["docs/learn/hoon/workbook/bomb"]
6+++
7In this exercise, we will build a generator that takes a list of wires to be cut
8in order to defuse a bomb. The bomb is defused according to the following rules.
10There are 6 possible colors of wire: white, black, purple, red, green, and
11orange.
13If you cut a white cable, you cannot cut white or black cable.
15If you cut a red cable, you must cut a green cable.
17If you cut a black cable, you cannot cut a white, green, or orange cable.
19If you cut an orange cable, you must cut a red or cable.
21If you cut a green cable, you must cut an orange or white cable.
23If you cut a purple cable, you cannot cut a purple, green, orange, or white
24cable.
26If the list of cuts does not result in the bomb exploding, the output should be
27a tape `bomb defused`. If any of the rules were broken, it should output the
28tape `boom`.
31```hoon
32!:
33:- %say
34|= [* [cuts=(list tape) ~] ~]
35:- %noun
36=<
37(defuse cuts)
38|%
39++ defuse
40 |= cuts=(list tape)
41 =| bad=(list tape)
42 |-
43 ?~ cuts
44 "bomb defused"
45 =/ cut i.cuts
46 ?~ bad
47 $(bad (~(got by rules) cut), cuts t.cuts)
48 ?~ (find [cut ~] bad)
49 $(bad (~(got by rules) cut), cuts t.cuts)
50 "boom"
51++ rules
52 %- ~(gas by *(map tape (list tape)))
53 :~ :- "white"
54 :~ "white"
55 "black"
56 ==
57 :- "red"
58 :~ "white"
59 "red"
60 "black"
61 "orange"
62 "purple"
63 ==
64 :- "black"
65 :~ "white"
66 "green"
67 "orange"
68 ==
69 :- "orange"
70 :~ "white"
71 "orange"
72 "green"
73 "purple"
74 ==
75 :- "green"
76 :~ "red"
77 "black"
78 "green"
79 "purple"
80 ==
81 :- "purple"
82 :~ "purple"
83 "green"
84 "orange"
85 "white"
86 ==
87 ==
88--
89```
91The start of our generator is simple enough. The `!:` in the first line enables
92a full stack trace in the event of an error. The following three lines create a
93`%say` generator that takes a list of tape as an argument.
95We next use the `=<` rune to compose two hoons, inverted. Remember that it's
96good Hoon style is to have the heaviest parts to the bottom -- that's what we're
97doing here.
99We call `defuse` and pass it `cuts`, the list of tapes we were provided with
100when the generator started.
102Next is the core that has two arms, `defuse` and `rules`. Let's look at `rules`
103quickly.
105We can see that it is a `map` of `tape` to `list` of `tape`. For each of the
106rules above we have specified when you cut a wire, which of the other wires you
107cannot cut. This required some reformulating of the rules given to use at the
108start, but it is much simpler to work with.
110```hoon
111++ defuse
112 |= cuts=(list tape)
113 =| bad=(list tape)
114 |-
115 ?~ cuts
116 "bomb defused"
117 =/ cut i.cuts
118 ?~ bad
119 $(bad (~(got by rules) cut), cuts t.cuts)
120 ?~ (find [cut ~] bad)
121 $(bad (~(got by rules) cut), cuts t.cuts)
122 "boom"
123```
125The `defuse` arm is the meat of our program. It is a `gate` that takes a `list`
126of `tape`. We combine a defaulted `list` of `tape` with the face `bad` with the
127subject.
129If `cuts` is empty, the bomb has been successfully defused.
131Otherwise, we give `i.cuts`, the first item in the list, a face called `cut`.
133If `bad` is empty, we recurse. This recursion sets `bad` to be the list of
134wires we can not cut from the `rules` map and make `cuts` `t.cuts` or the tail
135of `cuts`, removing the first element of the list.
137If `bad` is not empty, we want to search inside of it for the current `cut`. If
138it's not listed, then we are safe to continue and recurse to process the rest of
139the cuts. However, if it is found in the bad list, the user has failed and the
140bomb explodes.