kapusta 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +50 -11
  3. data/bin/check-all +6 -1
  4. data/bin/compile-examples +7 -2
  5. data/examples/anagram.kap +3 -3
  6. data/examples/app/args.kap +9 -0
  7. data/examples/arrange-coins.kap +3 -3
  8. data/examples/baseball-game.kap +5 -5
  9. data/examples/best-time-to-buy-sell-stock.kap +2 -2
  10. data/examples/binary-search.kap +2 -2
  11. data/examples/binary-to-decimal.kap +1 -1
  12. data/examples/blocks-and-kwargs.kap +2 -2
  13. data/examples/count-effects.kap +1 -1
  14. data/examples/count-items-matching-rule.kap +18 -0
  15. data/examples/doto-hygiene.kap +2 -2
  16. data/examples/doto.kap +2 -2
  17. data/examples/egg-count.kap +1 -1
  18. data/examples/exceptions.kap +1 -1
  19. data/examples/falling-drops.kap +7 -7
  20. data/examples/fennel-parity-examples.txt +3 -6
  21. data/examples/good-pairs.kap +18 -0
  22. data/examples/greet.kap +1 -1
  23. data/examples/happy-number.kap +2 -2
  24. data/examples/left-right-difference.kap +60 -0
  25. data/examples/length-of-last-word.kap +4 -4
  26. data/examples/manhattan-distance.kap +1 -1
  27. data/examples/maximum-subarray.kap +23 -7
  28. data/examples/minimum-start-value.kap +19 -0
  29. data/examples/move-zeroes.kap +2 -2
  30. data/examples/mruby-runtime-examples.txt +8 -2
  31. data/examples/non-constant-local.kap +1 -1
  32. data/examples/number-of-1-bits.kap +1 -1
  33. data/examples/number-of-steps.kap +1 -1
  34. data/examples/palindrome.kap +2 -2
  35. data/examples/pangram.kap +4 -4
  36. data/examples/pcall.kap +3 -3
  37. data/examples/pipeline.kap +4 -4
  38. data/examples/plus-one.kap +3 -3
  39. data/examples/raindrops.kap +1 -1
  40. data/examples/range-width.kap +14 -0
  41. data/examples/recent-counter.kap +6 -6
  42. data/examples/require-local-args.kap +9 -0
  43. data/examples/require-local.kap +7 -0
  44. data/examples/require-module-local.kap +4 -0
  45. data/examples/require-module.kap +4 -0
  46. data/examples/reverse-integer.kap +1 -1
  47. data/examples/roman-to-integer.kap +3 -3
  48. data/examples/running-sum.kap +20 -0
  49. data/examples/safe-lookup.kap +2 -2
  50. data/examples/single-number.kap +1 -1
  51. data/examples/stack.kap +14 -14
  52. data/examples/subtract-product-sum.kap +1 -1
  53. data/examples/summary-ranges.kap +45 -0
  54. data/examples/threading.kap +5 -5
  55. data/examples/tset.kap +1 -1
  56. data/examples/two-sum-hash.kap +3 -3
  57. data/examples/two-sum.kap +1 -1
  58. data/examples/ugly-number.kap +1 -1
  59. data/examples/underground-system.kap +39 -0
  60. data/examples/valid-parentheses-1.kap +6 -6
  61. data/exe/kapusta-ls +49 -2
  62. data/lib/kapusta/ast.rb +8 -0
  63. data/lib/kapusta/compiler/emitter/bindings.rb +111 -89
  64. data/lib/kapusta/compiler/emitter/collections.rb +32 -40
  65. data/lib/kapusta/compiler/emitter/control_flow.rb +33 -31
  66. data/lib/kapusta/compiler/emitter/expressions.rb +21 -5
  67. data/lib/kapusta/compiler/emitter/interop.rb +169 -78
  68. data/lib/kapusta/compiler/emitter/patterns.rb +12 -14
  69. data/lib/kapusta/compiler/emitter/simple_expression.rb +114 -0
  70. data/lib/kapusta/compiler/emitter/support.rb +63 -81
  71. data/lib/kapusta/compiler/emitter.rb +1 -0
  72. data/lib/kapusta/compiler/language.rb +522 -0
  73. data/lib/kapusta/compiler/lua_compat.rb +23 -28
  74. data/lib/kapusta/compiler/macro_expander.rb +30 -30
  75. data/lib/kapusta/compiler/macro_lowerer.rb +12 -24
  76. data/lib/kapusta/compiler/normalizer.rb +25 -17
  77. data/lib/kapusta/compiler.rb +3 -24
  78. data/lib/kapusta/env.rb +2 -2
  79. data/lib/kapusta/errors.rb +2 -1
  80. data/lib/kapusta/formatter/ast_helpers.rb +78 -0
  81. data/lib/kapusta/formatter/cli.rb +125 -0
  82. data/lib/kapusta/formatter/line_helpers.rb +44 -0
  83. data/lib/kapusta/formatter/validator.rb +32 -0
  84. data/lib/kapusta/formatter.rb +354 -325
  85. data/lib/kapusta/lsp/identifier.rb +1 -1
  86. data/lib/kapusta/lsp/rename.rb +21 -11
  87. data/lib/kapusta/lsp/scope_walker.rb +122 -212
  88. data/lib/kapusta/lsp/workspace_index.rb +17 -5
  89. data/lib/kapusta/reader.rb +4 -2
  90. data/lib/kapusta/version.rb +1 -1
  91. data/lib/kapusta.rb +39 -6
  92. data/spec/cli_spec.rb +13 -0
  93. data/spec/examples_errors_spec.rb +3 -1
  94. data/spec/examples_spec.rb +67 -15
  95. data/spec/formatter_spec.rb +246 -0
  96. data/spec/lsp_spec.rb +69 -0
  97. data/spec/require_spec.rb +294 -0
  98. metadata +21 -2
  99. data/examples/describe.kap +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9324827934a0647689027ecf5fc6bf83708fe536cd904dc04d1f9c0594c37581
4
- data.tar.gz: 736a8f7d8158fc4502415168f5791d7af8b98f392800255576c1d0182ef920c6
3
+ metadata.gz: e247dd5e305dcac681bcdb9decbf30d8e0628232626f751c2f39fe8d79796e02
4
+ data.tar.gz: 6d1e24c986c1301045e469b03a76295e03276cee031939ac87dea34187931251
5
5
  SHA512:
6
- metadata.gz: 62e4118362c7fbe7ae034470a01ddf37a0bb826fb142e2611d72b09ded1777e52bf2b078cf48c0283dda6f0a8c5989ec31f60d0913cf16ec3ac9ccabf2c40626
7
- data.tar.gz: 5fbd5b3a7809eff626c43203b1c36761efac10cb5663ca345ace26fbea731da63402909be6a04f22aedaca80945e1db3456209a6ac335b8fc4a2152bcc198395
6
+ metadata.gz: 919382905342cffcbf1b6986a232f9050dcacfeb196fab8131d9d72a462d8c741e560fe1b72922998bb980a8fb3eeecbda9c348acd694b3299d890b44022132c
7
+ data.tar.gz: 50e77ee9da2df8b1a2f6e694b205dde09e2631d6b49cbc9ddd9cc022e2f86122055abd721d5a82f76af1a2004e78e0f14f2a1b4d02c16cbfb8ee09fb1397a900
data/README.md CHANGED
@@ -92,20 +92,59 @@ p ack(2, 3)
92
92
  p ack(3, 3)
93
93
  ```
94
94
 
95
+ ## Calls and lookup
96
+
97
+ Hash lookup uses `:`.
98
+
99
+ ```fennel
100
+ user:name
101
+ (: user :name)
102
+ (?: user :profile :name) ; safe lookup
103
+ ```
104
+
105
+ Method calls use `.`.
106
+
107
+ ```fennel
108
+ user.name
109
+ (. user :name)
110
+ ```
111
+
112
+ Kapusta source always uses `require`.
113
+
114
+ ```fennel
115
+ (require :app.args)
116
+ (local messages (require :app.messages))
117
+ (require "./config")
118
+ ```
119
+
120
+ Compiled Ruby uses the Ruby form that fits:
121
+
122
+ ```ruby
123
+ require "app/args"
124
+ require "app/messages"
125
+ messages = App::Messages
126
+ require_relative "config"
127
+ ```
128
+
129
+ For larger programs, organize code with Kapusta's Ruby host forms:
130
+
131
+ 1. Use `module` + `defn` for stateless functions.
132
+ 2. Use `class` + `fn` for state or dependencies.
133
+ 3. Avoid returning hashes of functions as the main app structure.
134
+
95
135
  ## Comparison with Fennel
96
136
 
97
137
  Kapusta keeps most core Fennel forms. The main differences come from Ruby's runtime and object model.
98
138
 
99
- | Fennel | Kapusta |
100
- |---------------------------------------|-------------------------------------------------------|
101
- | Lua stdlib | Ruby stdlib |
102
- | `:foo` is a Lua string | `:foo` is a Ruby symbol |
103
- | `(. xs 1)` is the first element | `(. xs 0)` is the first element |
104
- | `string.format`, `table.insert`, etc. | use Ruby methods and stdlib instead |
105
- | `values` uses Lua multiple returns | `values` lowers to a Ruby array, usually destructured |
106
- | `(print x)` is Lua's `print` (bare) | `(print x)` is Ruby's `p` (inspect-style) |
107
- | `(.. "x: " nil)` errors at runtime | `(.. "x: " nil)` produces `"x: "` (Ruby `nil.to_s`) |
108
- | `with-open`, `tail!` | not provided |
139
+ | Fennel | Kapusta |
140
+ |---------------------------------------|-----------------------------------------------------|
141
+ | Lua stdlib | Ruby stdlib |
142
+ | `:foo` is a Lua string | `:foo` is a Ruby symbol |
143
+ | `(. xs 1)` is the first element | `(: xs 0)` is the first element |
144
+ | `string.format`, `table.insert`, etc. | use Ruby methods and stdlib instead |
145
+ | `(print x)` is Lua's `print` (bare) | `(print x)` is Ruby's `p` (inspect-style) |
146
+ | `(.. "x: " nil)` errors at runtime | `(.. "x: " nil)` produces `"x: "` (Ruby `nil.to_s`) |
147
+ | `with-open`, `tail!` | not provided |
109
148
 
110
149
  Kapusta-specific additions:
111
150
 
@@ -116,7 +155,7 @@ Kapusta-specific additions:
116
155
  - `try` / `catch` / `finally` plus `raise` for exceptions
117
156
  - `(ruby "...")` raw host escape hatch
118
157
  - pass Ruby keyword arguments by ending a call with a symbol-keyed hash: `(File.open path "r" {:encoding "UTF-8"})`
119
- - pass a Ruby block by ending a call with a `(fn ...)` or `#(...)` literal: `(File.open path "r" (fn [io] (: io :read)))`
158
+ - pass a Ruby block by ending a call with a `(fn ...)` or `#(...)` literal: `(File.open path "r" (fn [io] io.read))`
120
159
 
121
160
  ## Format
122
161
 
data/bin/check-all CHANGED
@@ -8,7 +8,12 @@ echo "== rubocop -A =="
8
8
  bundle exec rubocop -A
9
9
 
10
10
  echo "== kapfmt =="
11
- for file in examples/*.kap; do ./exe/kapfmt --fix "$file"; done
11
+ while IFS= read -r file; do
12
+ ./exe/kapfmt --fix "$file"
13
+ done < <(find examples -type f -name '*.kap' | sort)
14
+
15
+ echo "== kapusta-ls =="
16
+ ./exe/kapusta-ls --lint examples
12
17
 
13
18
  echo "== fennel parity =="
14
19
  bin/fennel-parity
data/bin/compile-examples CHANGED
@@ -63,7 +63,10 @@ fi
63
63
  mkdir -p "$TARGET_DIR"
64
64
 
65
65
  shopt -s nullglob
66
- kap_files=("$SOURCE_DIR"/*.kap)
66
+ kap_files=()
67
+ while IFS= read -r kap_file; do
68
+ kap_files+=("$kap_file")
69
+ done < <(find "$SOURCE_DIR" -type f -name '*.kap' | sort)
67
70
 
68
71
  if ((${#kap_files[@]} == 0)); then
69
72
  printf 'No .kap files found in %s\n' "$SOURCE_DIR" >&2
@@ -71,9 +74,11 @@ if ((${#kap_files[@]} == 0)); then
71
74
  fi
72
75
 
73
76
  for kap_file in "${kap_files[@]}"; do
74
- name="$(basename "$kap_file" .kap)"
77
+ relative_name="${kap_file#"$SOURCE_DIR"/}"
78
+ name="${relative_name%.kap}"
75
79
  ruby_file="$TARGET_DIR/$name.rb"
76
80
  mruby_file="$TARGET_DIR/$name-mruby.rb"
81
+ mkdir -p "$(dirname "$ruby_file")"
77
82
 
78
83
  "$ROOT_DIR/exe/kapusta" --compile "$kap_file" > "$ruby_file"
79
84
  printf 'Compiled %s -> %s\n' "$kap_file" "$ruby_file"
data/examples/anagram.kap CHANGED
@@ -1,8 +1,8 @@
1
1
  (fn normalize-word [word]
2
2
  (-> word
3
- (: :downcase)
4
- (: :chars)
5
- (: :sort)))
3
+ (. :downcase)
4
+ (. :chars)
5
+ (. :sort)))
6
6
 
7
7
  (fn anagram? [a b]
8
8
  (= (normalize-word a)
@@ -0,0 +1,9 @@
1
+ (module App.Args)
2
+
3
+ (defn parse [argv]
4
+ {:command (: argv 0) :target (: argv 1)})
5
+
6
+ (defn format-command [parsed]
7
+ (.. (: parsed :command) " -> " (: parsed :target)))
8
+
9
+ (end)
@@ -1,15 +1,15 @@
1
1
  (fn arrange-coins [n]
2
2
  (let [rows (faccumulate [acc {:sum 0 :rows 0} i 1 n]
3
- (let [new-sum (+ (. acc :sum) i)]
3
+ (let [new-sum (+ acc:sum i)]
4
4
  (if (<= new-sum n)
5
5
  {:sum new-sum :rows i}
6
6
  acc)))
7
7
  used (faccumulate [acc {:sum 0 :rows 0} i 1 n]
8
- (let [new-sum (+ (. acc :sum) i)]
8
+ (let [new-sum (+ acc:sum i)]
9
9
  (if (<= new-sum n)
10
10
  {:sum new-sum :rows i}
11
11
  acc)))]
12
- [(. rows :rows) (. used :sum)]))
12
+ [rows:rows used:sum]))
13
13
 
14
14
  (let [[r u] (arrange-coins 0)]
15
15
  (print r)
@@ -1,11 +1,11 @@
1
1
  (fn cal-points [ops]
2
2
  (let [scores []]
3
3
  (each [op ops]
4
- (if (= op "C") (do (-?> (scores.pop) (: :abs)) nil)
5
- (= op "D") (scores.push (* 2 (. scores -1)))
6
- (= op "+") (scores.push (+ (. scores -1) (. scores -2)))
7
- (scores.push (: op :to-i))))
8
- scores.sum))
4
+ (if (= op "C") (do (. (. scores :pop) :abs) nil)
5
+ (= op "D") (. scores :push (* 2 (: scores -1)))
6
+ (= op "+") (. scores :push (+ (: scores -1) (: scores -2)))
7
+ (. scores :push (. op :to-i))))
8
+ (. scores :sum)))
9
9
 
10
10
  (print (cal-points ["5" "2" "C" "D" "+"]))
11
11
  (print (cal-points ["5" "-2" "4" "C" "D" "9" "+" "+"]))
@@ -1,8 +1,8 @@
1
1
  (fn max-profit [prices]
2
- (var min-price (. prices 0))
2
+ (var min-price (: prices 0))
3
3
  (var best 0)
4
4
  (for [i 1 (- (length prices) 1)]
5
- (let [p (. prices i)]
5
+ (let [p (: prices i)]
6
6
  (when (< p min-price) (set min-price p))
7
7
  (when (> (- p min-price) best) (set best (- p min-price)))))
8
8
  best)
@@ -3,8 +3,8 @@
3
3
  (var hi (- (length xs) 1))
4
4
  (var answer nil)
5
5
  (while (and (<= lo hi) (= answer nil))
6
- (let [mid (: (/ (+ lo hi) 2) :floor)
7
- guess (. xs mid)]
6
+ (let [mid (. (/ (+ lo hi) 2) :floor)
7
+ guess (: xs mid)]
8
8
  (if (= guess target) (set answer mid)
9
9
  (< guess target) (set lo (+ mid 1))
10
10
  (set hi (- mid 1)))))
@@ -1,6 +1,6 @@
1
1
  (fn binary-to-decimal [bits]
2
2
  (faccumulate [value 0 i 0 (- (length bits) 1)]
3
- (+ (* value 2) (if (= (. bits i) "1") 1 0))))
3
+ (+ (* value 2) (if (= (: bits i) "1") 1 0))))
4
4
 
5
5
  (print (binary-to-decimal "1011"))
6
6
  (print (binary-to-decimal "0"))
@@ -8,12 +8,12 @@
8
8
  (File.open path
9
9
  "w"
10
10
  {:encoding "UTF-8"}
11
- (fn [io] (: io :write "Ada\nLin\n")))
11
+ (fn [io] (io.write "Ada\nLin\n")))
12
12
  (File.open path
13
13
  "r"
14
14
  {:encoding "UTF-8"}
15
15
  (fn [io]
16
- (let [content (: io :read)]
16
+ (let [content (io.read)]
17
17
  (print (content.strip))
18
18
  (print (length (content.lines)))))))
19
19
  (finally
@@ -2,7 +2,7 @@
2
2
  (var quits 0)
3
3
  (var moves 0)
4
4
  (each [_ effect (ipairs effects)]
5
- (case (. effect :kind)
5
+ (case effect:kind
6
6
  :quit (set quits (+ quits 1))
7
7
  :move (set moves (+ moves 1))
8
8
  _ nil))
@@ -0,0 +1,18 @@
1
+ (local rule-keys {"type" :type
2
+ "color" :color
3
+ "name" :name
4
+ "rating" :rating
5
+ "category" :category
6
+ "owner" :owner})
7
+
8
+ (fn count-matches [items rule-key rule-value]
9
+ (let [key (: rule-keys rule-key)]
10
+ (accumulate [count 0 _ item (ipairs items)]
11
+ (if (= (: item key) rule-value) (+ count 1) count))))
12
+
13
+ (let [items [{:type "phone" :color "blue" :name "pixel"}
14
+ {:type "computer" :color "silver" :name "lenovo"}
15
+ {:type "phone" :color "gold" :name "iphone"}]]
16
+ (print (count-matches items "type" "phone"))
17
+ (print (count-matches items "color" "silver"))
18
+ (print (count-matches items "name" "pixel")))
@@ -1,5 +1,5 @@
1
1
  (let [__doto__ 99
2
2
  xs []]
3
3
  (doto xs
4
- (: :push __doto__))
5
- (print (xs.inspect)))
4
+ (. :push __doto__))
5
+ (print (. xs :inspect)))
data/examples/doto.kap CHANGED
@@ -1,2 +1,2 @@
1
- (let [xs (doto [] (: :push 1) (: :push 2) (: :push 3))]
2
- (print (xs.join ", ")))
1
+ (let [xs (doto [] (. :push 1) (. :push 2) (. :push 3))]
2
+ (print (. xs :join ", ")))
@@ -4,7 +4,7 @@
4
4
  (var eggs 0)
5
5
  (while (> n 0)
6
6
  (when (odd? n) (set eggs (+ eggs 1)))
7
- (set n (: (/ n 2) :floor)))
7
+ (set n (. (/ n 2) :floor)))
8
8
  eggs)
9
9
 
10
10
  (print (egg-count 30))
@@ -1,7 +1,7 @@
1
1
  (fn require-score [s]
2
2
  (if (= s "oops")
3
3
  (raise (ArgumentError.new "not a number"))
4
- (: s :to-i)))
4
+ s.to-i))
5
5
 
6
6
  (fn parse-score [s]
7
7
  (try (require-score s)
@@ -1,12 +1,12 @@
1
1
  (fn step [drops]
2
2
  (each [_ drop (ipairs drops)]
3
- (let [falling {:kind (. drop :kind)
4
- :x (. drop :x)
5
- :y (+ (. drop :y) (. drop :speed))
6
- :w (. drop :w)
7
- :h (. drop :h)
8
- :speed (. drop :speed)}]
9
- (print (. falling :kind) (. falling :x) (. falling :y)))))
3
+ (let [falling {:kind drop:kind
4
+ :x drop:x
5
+ :y (+ drop:y drop:speed)
6
+ :w drop:w
7
+ :h drop:h
8
+ :speed drop:speed}]
9
+ (print falling:kind falling:x falling:y))))
10
10
 
11
11
  (step [{:kind "rain" :x 0 :y 0 :w 1 :h 1 :speed 2}
12
12
  {:kind "snow" :x 5 :y 1 :w 1 :h 1 :speed 1}])
@@ -1,19 +1,15 @@
1
1
  ackermann
2
2
  anonymous-greeter
3
3
  array-sign
4
- arrange-coins
5
4
  case-vs-match
6
5
  classify-wallet
7
6
  climbing-stairs
8
7
  convert-temperature
9
- count-effects
10
- describe
11
8
  destructure
12
9
  divisibility-stats
13
10
  equal-sums
14
11
  even-squares
15
12
  factorial
16
- falling-drops
17
13
  fib
18
14
  fizzbuzz
19
15
  gcd
@@ -30,18 +26,19 @@ macros-unless
30
26
  macros-when-let
31
27
  match
32
28
  max-achievable
29
+ maximum-subarray
33
30
  min-max
34
31
  nested-nil-pattern
35
- non-constant-local
36
32
  or-patterns
37
33
  packet-router
38
34
  points
39
35
  power-of-three
40
36
  primes
41
- safe-lookup
37
+ range-width
42
38
  shapes
43
39
  squares
44
40
  sum
41
+ summary-ranges
45
42
  thread-styles
46
43
  tic-tac-toe
47
44
  underscore-patterns
@@ -0,0 +1,18 @@
1
+ (fn add-good-pairs [pairs counts n]
2
+ (let [prev (or (: counts n) 0)
3
+ next-pairs (+ pairs prev)]
4
+ (tset counts n (+ prev 1))
5
+ (values next-pairs counts)))
6
+
7
+ (fn num-identical-pairs [nums]
8
+ (var pairs 0)
9
+ (var counts {})
10
+ (each [_ n (ipairs nums)]
11
+ (let [(next-pairs next-counts) (add-good-pairs pairs counts n)]
12
+ (set pairs next-pairs)
13
+ (set counts next-counts)))
14
+ pairs)
15
+
16
+ (print (num-identical-pairs [1 2 3 1 1 3]))
17
+ (print (num-identical-pairs [1 1 1 1]))
18
+ (print (num-identical-pairs [1 2 3]))
data/examples/greet.kap CHANGED
@@ -1,2 +1,2 @@
1
- (let [name (or (. ARGV 0) "world")]
1
+ (let [name (or (: ARGV 0) "world")]
2
2
  (print (.. "Hello, " name "!")))
@@ -4,13 +4,13 @@
4
4
  (while (> x 0)
5
5
  (let [d (% x 10)]
6
6
  (set total (+ total (* d d)))
7
- (set x (: (/ x 10) :floor))))
7
+ (set x (. (/ x 10) :floor))))
8
8
  total)
9
9
 
10
10
  (fn happy? [n]
11
11
  (let [seen {}]
12
12
  (var x n)
13
- (while (and (not= x 1) (not (seen.key? x)))
13
+ (while (and (not= x 1) (not (. seen :key? x)))
14
14
  (tset seen x true)
15
15
  (set x (sum-of-squares x)))
16
16
  (= x 1)))
@@ -0,0 +1,60 @@
1
+ (fn same-list? [a b]
2
+ (var ok (= (length a) (length b)))
3
+ (each [i value (ipairs a)]
4
+ (when (not (= value (: b i)))
5
+ (set ok false)))
6
+ ok)
7
+
8
+ (fn abs [n]
9
+ (if (< n 0) (- n) n))
10
+
11
+ (fn left-right-difference [nums]
12
+ (let [total (accumulate [sum 0 _ n (ipairs nums)] (+ sum n))]
13
+ (var left 0)
14
+ (icollect [_ n (ipairs nums)]
15
+ (do
16
+ (let [right (- total left n)
17
+ diff (abs (- left right))]
18
+ (set left (+ left n))
19
+ diff)))))
20
+
21
+ (print (same-list? [209
22
+ 206
23
+ 201
24
+ 194
25
+ 185
26
+ 174
27
+ 161
28
+ 146
29
+ 129
30
+ 110
31
+ 89
32
+ 66
33
+ 41
34
+ 14
35
+ 15
36
+ 46
37
+ 79
38
+ 114
39
+ 151
40
+ 190]
41
+ (left-right-difference [1
42
+ 2
43
+ 3
44
+ 4
45
+ 5
46
+ 6
47
+ 7
48
+ 8
49
+ 9
50
+ 10
51
+ 11
52
+ 12
53
+ 13
54
+ 14
55
+ 15
56
+ 16
57
+ 17
58
+ 18
59
+ 19
60
+ 20])))
@@ -1,9 +1,9 @@
1
1
  (fn length-of-last-word [s]
2
2
  (-> s
3
- (: :strip)
4
- (: :split)
5
- (. -1)
6
- (: :length)))
3
+ (. :strip)
4
+ (. :split)
5
+ (: -1)
6
+ (. :length)))
7
7
 
8
8
  (print (length-of-last-word "Hello World"))
9
9
  (print (length-of-last-word " fly me to the moon "))
@@ -1,6 +1,6 @@
1
1
  (fn manhattan [edge]
2
2
  (let [{:from [x1 y1] :to [x2 y2]} edge]
3
- (+ (: (- x1 x2) :abs) (: (- y1 y2) :abs))))
3
+ (+ (. (- x1 x2) :abs) (. (- y1 y2) :abs))))
4
4
 
5
5
  (fn total-distance [edges]
6
6
  (accumulate [total 0 _ edge (ipairs edges)]
@@ -1,11 +1,27 @@
1
+ (fn max-subarray-step [current best n]
2
+ (let [extended (+ current n)
3
+ next-current (if (> extended n) extended n)
4
+ next-best (if (> next-current best) next-current best)]
5
+ (values next-current next-best)))
6
+
7
+ (fn max-subarray-state [nums]
8
+ (var current 0)
9
+ (var best 0)
10
+ (var initialized? false)
11
+ (each [_ n (ipairs nums)]
12
+ (if initialized?
13
+ (let [(next-current next-best) (max-subarray-step current best n)]
14
+ (set current next-current)
15
+ (set best next-best))
16
+ (do
17
+ (set current n)
18
+ (set best n)
19
+ (set initialized? true))))
20
+ (values current best))
21
+
1
22
  (fn max-subarray [nums]
2
- (var best (. nums 0))
3
- (var curr (. nums 0))
4
- (for [i 1 (- (length nums) 1)]
5
- (let [n (. nums i)]
6
- (set curr (if (> (+ curr n) n) (+ curr n) n))
7
- (when (> curr best) (set best curr))))
8
- best)
23
+ (let [(_current best) (max-subarray-state nums)]
24
+ best))
9
25
 
10
26
  (print (max-subarray [-2 1 -3 4 -1 2 1 -5 4]))
11
27
  (print (max-subarray [1]))
@@ -0,0 +1,19 @@
1
+ (fn minimum-start-value [nums]
2
+ (var prefix 0)
3
+ (var lowest 0)
4
+ (each [_ n (ipairs nums)]
5
+ (set prefix (+ prefix n))
6
+ (when (< prefix lowest) (set lowest prefix)))
7
+ (values (+ 1 (- lowest)) prefix))
8
+
9
+ (let [[start total] (minimum-start-value [-3 2 -3 4 2])]
10
+ (print start)
11
+ (print total))
12
+
13
+ (let [[start total] (minimum-start-value [1 2])]
14
+ (print start)
15
+ (print total))
16
+
17
+ (let [[start total] (minimum-start-value [1 -2 -3])]
18
+ (print start)
19
+ (print total))
@@ -1,8 +1,8 @@
1
1
  (fn move-zeroes [nums]
2
2
  (var write 0)
3
3
  (for [read 0 (- (length nums) 1)]
4
- (when (not= (. nums read) 0)
5
- (tset nums write (. nums read))
4
+ (when (not= (: nums read) 0)
5
+ (tset nums write (: nums read))
6
6
  (set write (+ write 1))))
7
7
  (for [i write (- (length nums) 1)]
8
8
  (tset nums i 0))
@@ -19,8 +19,8 @@ climbing-stairs
19
19
  contains-duplicate
20
20
  convert-temperature
21
21
  count-effects
22
+ count-items-matching-rule
22
23
  counter
23
- describe
24
24
  destructure
25
25
  divisibility-stats
26
26
  doto
@@ -33,12 +33,14 @@ falling-drops
33
33
  fib
34
34
  fizzbuzz
35
35
  gcd
36
+ good-pairs
36
37
  greet
37
38
  happy-number
38
39
  hashfn
39
40
  hit-counter
40
41
  kwargs
41
42
  leap-year
43
+ left-right-difference
42
44
  length-of-last-word
43
45
  macros-dbg
44
46
  macros-import
@@ -55,9 +57,10 @@ match
55
57
  max-achievable
56
58
  maximum-subarray
57
59
  min-max
60
+ minimum-start-value
58
61
  module-header
59
- nested-nil-pattern
60
62
  move-zeroes
63
+ nested-nil-pattern
61
64
  number-of-1-bits
62
65
  number-of-steps
63
66
  or-patterns
@@ -70,11 +73,13 @@ points
70
73
  power-of-three
71
74
  primes
72
75
  raindrops
76
+ range-width
73
77
  recent-counter
74
78
  record
75
79
  reverse-integer
76
80
  roman-to-integer
77
81
  ruby-eval
82
+ running-sum
78
83
  safe-lookup
79
84
  scopes
80
85
  shapes
@@ -84,6 +89,7 @@ squares
84
89
  stack
85
90
  subtract-product-sum
86
91
  sum
92
+ summary-ranges
87
93
  thread-styles
88
94
  threading
89
95
  tic-tac-toe
@@ -8,4 +8,4 @@
8
8
  (print (regular-fn 5))
9
9
  (print (lambda-fn 5))
10
10
  (print (length vec-binding))
11
- (print (. hash-binding :a))
11
+ (print hash-binding:a)
@@ -5,7 +5,7 @@
5
5
  (var count 0)
6
6
  (for [_ 1 BIT-WIDTH]
7
7
  (set count (+ count (% x 2)))
8
- (set x (: (/ x 2) :floor)))
8
+ (set x (. (/ x 2) :floor)))
9
9
  count)
10
10
 
11
11
  (print (hamming-weight 11))
@@ -5,7 +5,7 @@
5
5
  (var steps 0)
6
6
  (while (not= x target)
7
7
  (if (= 0 (% x 2))
8
- (set x (: (/ x 2) :floor))
8
+ (set x (. (/ x 2) :floor))
9
9
  (set x (- x 1)))
10
10
  (set steps (+ steps 1)))
11
11
  steps)
@@ -1,6 +1,6 @@
1
1
  (fn palindrome? [s]
2
- (let [normalized (-> s (: :downcase) (: :gsub (ruby "/[^a-z]/") ""))]
3
- (= normalized (: normalized :reverse))))
2
+ (let [normalized (-> s (. :downcase) (. :gsub (ruby "/[^a-z]/") ""))]
3
+ (= normalized (. normalized :reverse))))
4
4
 
5
5
  (print (palindrome? "racecar"))
6
6
  (print (palindrome? "A man, a plan, a canal: Panama"))