Skip to content

Instantly share code, notes, and snippets.

@timmc
Last active December 15, 2016 15:24
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timmc/3916042 to your computer and use it in GitHub Desktop.
Save timmc/3916042 to your computer and use it in GitHub Desktop.
rest in curje [now called swearjure]
;; An exercise in writing #'rest without [0-9a-zA-Z], by Tim McCormack
;; Note that the input must be a vector, although the code could easily be
;; modified to vector-ify any input coll.
;; Let's take this a step at a time...
(#(((% 1) :main) %) ;; call the main method with the input and fns
[[0 1 2 3 4 5] ;; the input is hardcoded here
;; fns are accessed by static indices into the fn table
{:main #(if (= (% 0) [])
;; empty input -> []
[]
;; recur with extra accumulator args
(((% 1) :loop)
[(% 0) (% 1) {:nexdex 1 :accum []}]))
:loop #(if (= (% 0) (vec (concat [((% 0) 0)]
((% 2) :accum))))
;; if first + rest = input, we're done
((% 2) :accum)
;; otherwise recur with new accumulator
(((% 1) :loop)
[(% 0) (% 1) {:nexdex (+ 1 ((% 2) :nexdex))
:accum (vec (concat ((% 2) :accum)
[((% 0) ((% 2) :nexdex))]))}]))
}])
;; Translate vec/concat expressions
(#(((% 1) :main) %) ;; call the main method with the input and fns
[[0 1 2 3 4 5] ;; the input is hardcoded here
;; fns are accessed by static indices into the fn table
{:main #(if (= (% 0) [])
;; empty input -> []
[]
;; recur with extra accumulator args
(((% 1) :loop)
[(% 0) (% 1) {:nexdex 1 :accum []}]))
:loop #(if (= (% 0) `[~((% 0) 0)
~@((% 2) :accum)])
;; if first + rest = input, we're done
((% 2) :accum)
;; otherwise recur with new accumulator
(((% 1) :loop)
[(% 0) (% 1) {:nexdex (+ 1 ((% 2) :nexdex))
:accum `[~@((% 2) :accum)
~((% 0) ((% 2) :nexdex))]}]))
}])
;; Translate if statements into explicit delayed eval and map dispatch
(#(((% 1) :main) %) ;; call the main method with the input and fns
[[0 1 2 3 4 5] ;; the input is hardcoded here
;; fns are accessed by static indices into the fn table
{:main #(({[] ((% 1) :always-empty)} ;; empty input -> []
(% 0) ;; dispatch on input's value
;; else, recur with extra accumulator args
((% 1) :do-recur))
[(% 0) (% 1)])
:always-empty #({} %& [])
:do-recur #(((% 1) :loop)
[(% 0) (% 1) {:nexdex 1 :accum []}])
:loop #(({(% 0) ((% 1) :done)} ;; if first + rest = input, we're done
;; dispatch on first + accum-rest to see if it matches the input
`[~((% 0) 0)
~@((% 2) :accum)]
;; else, update accumulator args
((% 1) :incloop))
[(% 0) (% 1) (% 2)])
:done #((% 2) :accum)
:incloop #(((% 1) :loop)
[(% 0) (% 1) {:nexdex (+ 1 ((% 2) :nexdex))
:accum `[~@((% 2) :accum)
~((% 0) ((% 2) :nexdex))]}])}])
;; fns indexed in vector instead of named in map (same for accum args)
(#(((% 1) 0) %)
[[0 1 2 3 4 5]
[#(({[] ((% 1) 1)}
(% 0)
((% 1) 2))
[(% 0) (% 1)])
#({} %& [])
#(((% 1) 3)
[(% 0) (% 1) [1 []]])
#(({(% 0) ((% 1) 4)}
`[~((% 0) 0)
~@((% 2) 1)]
((% 1) 5))
[(% 0) (% 1) (% 2)])
#((% 2) 1)
#(((% 1) 3)
[(% 0) (% 1) [(+ 1 ((% 2) 0))
`[~@((% 2) 1)
~((% 0) ((% 2) 0))]]])]])
;; replace all the numeric literals with arithmetic expressions -- done!
(#(((% (+(*))) (+)) %)
[[:a :b :c :d :e] ;; input has alphanumeric for ease of reading
[#(({[] ((% (+(*))) (+(*)))}
(% (+))
((% (+(*))) (+(*)(*))))
[(% (+)) (% (+(*)))])
#({} %& [])
#(((% (+(*))) (+(*)(*)(*)))
[(% (+)) (% (+(*))) [(+(*)) []]])
#(({(% (+)) ((% (+(*))) (+(*)(*)(*)(*)))}
`[~((% (+)) (+))
~@((% (+(*)(*))) (+(*)))]
((% (+(*))) (+(*)(*)(*)(*)(*))))
[(% (+)) (% (+(*))) (% (+(*)(*)))])
#((% (+(*)(*))) (+(*)))
#(((% (+(*))) (+(*)(*)(*)))
[(% (+)) (% (+(*))) [(+ (+(*)) ((% (+(*)(*))) (+)))
`[~@((% (+(*)(*))) (+(*)))
~((% (+)) ((% (+(*)(*))) (+)))]]])]])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment