From ee509e05746731b12afe64bfe34284b119f6b4ae Mon Sep 17 00:00:00 2001 From: mryouse Date: Tue, 2 Aug 2022 02:16:38 +0000 Subject: exercises --- rosetta/factors-of-int.neb | 29 ++++++++++++++++++ rosetta/lev.neb | 20 +++++++++++++ rosetta/lines.neb | 16 ++++++++++ rosetta/luhn.neb | 73 ++++++++++++++++++++++++++++++++++++++++++++++ rosetta/palindrome.neb | 6 ++++ rosetta/sum-of-squares.neb | 2 ++ 6 files changed, 146 insertions(+) create mode 100644 rosetta/factors-of-int.neb create mode 100644 rosetta/lev.neb create mode 100644 rosetta/lines.neb create mode 100644 rosetta/luhn.neb create mode 100644 rosetta/palindrome.neb create mode 100644 rosetta/sum-of-squares.neb diff --git a/rosetta/factors-of-int.neb b/rosetta/factors-of-int.neb new file mode 100644 index 0000000..ea3ca15 --- /dev/null +++ b/rosetta/factors-of-int.neb @@ -0,0 +1,29 @@ +(func .list-of-num (num) + (def nums (list)) + (for-count num + (redef nums (append nums _idx_))) + nums) + +(func .rough-sqrt (num) (.rough-sqrt num 1)) + +(func .rough-sqrt (num val) + (branch + ((eq? (* val val) num) val) + ((> (* val val) num) (- val 1)) + (#true + (.rough-sqrt num (+ 1 val))))) + +(func factor-naive (num) + (filter (lambda (x) (int? (/ num x))) (.list-of-num num))) + +(func factor-better (num) + (append + (filter (lambda (x) (int? (/ num x))) (.list-of-num (floor (/ num 2)))) + num)) + +(func factor-even-better (num) + (def ret (list)) + (for-each (.list-of-num (.rough-sqrt num)) + (if (int? (/ num _item_)) + (redef ret (append ret (list _item_ (/ num _item_)))))) + ret) diff --git a/rosetta/lev.neb b/rosetta/lev.neb new file mode 100644 index 0000000..6797c41 --- /dev/null +++ b/rosetta/lev.neb @@ -0,0 +1,20 @@ +(func min (lst :{:int}) + (def val (first lst)) + (for-each (rest lst) + (if (< _item_ val) + (redef val _item_))) + val) + +(func lev (s t) + (branch + ((eq? 0 (length s)) (length t)) + ((eq? 0 (length t)) (length s)) + ((eq? (first s) (first t)) + (lev (rest s) (rest t))) + (#true + (+ 1 + (min + (list + (lev s (rest t)) + (lev (rest s) t) + (lev (rest s) (rest t)))))))) diff --git a/rosetta/lines.neb b/rosetta/lines.neb new file mode 100644 index 0000000..45a6a6f --- /dev/null +++ b/rosetta/lines.neb @@ -0,0 +1,16 @@ + +(func adjust (text width) + (def lines (list)) + (def word "") + (for-each (split text " ") + (branch + ((eq? 0 (length word)) (redef word _item_)) + ((<= (+ (length word) 1 (length _item_)) width) + (redef word (concat word " " _item_))) + (#true + (block + (redef lines (append lines word)) + (redef word _item_))))) + (if (not (eq? 0 (length word))) + (append lines word) + lines)) diff --git a/rosetta/luhn.neb b/rosetta/luhn.neb new file mode 100644 index 0000000..ac06e17 --- /dev/null +++ b/rosetta/luhn.neb @@ -0,0 +1,73 @@ +(func odd-elems (lst) + (odd-elems lst (list))) + +(func odd-elems (lst acc) + (if (eq? 0 (length lst)) + acc + (odd-elems (rest (rest lst)) (append acc (first lst))))) + +(func even-elems (lst) + (even-elems lst (list))) + +(func even-elems (lst acc) + (if (>= 1 (length lst)) + acc + (even-elems (rest (rest lst)) (append acc (first (rest lst)))))) + +(func luhn? (num) + ;; algo: + ;; with digits reversed, sum odd digits + ;; for all even digits: + ;; - double them + ;; - sum the digits (i.e. 16 -> 1 + 6 -> 7) + ;; - sum everything + ;; sum both values, and if the result ends in 0, it's valid + (def reverse-digits (reverse (->string num))) + ; sum the odd digits + (def s1 + (reduce + (lambda (x y) (+ x (string->int y))) + (odd-elems reverse-digits) 0)) + (def s2 + ; sum everything + (reduce (lambda (x y) (+ x y)) + ; sum each of the digits + (map (lambda (x) (apply + x)) + ; split the resulting numbers into digits + (map (lambda (x) (map string->int (split (->string x)))) + ; double the even digits + (map (lambda (x) (* 2 (string->int x))) + (even-elems reverse-digits)))) 0)) + (int? (/ (+ s1 s2) 10))) + +(func base36-to-base10 (value :string) + (base36-to-base10 (ord value))) + +(func base36-to-base10 (value :int) + (if (< value 32) + (+ 9 value) + (base36-to-base10 (- value 32)))) + +(func isin? (value) + ;; algo: + ;; - must be 12 digits + ;; - first 2 must be letters + ;; - last must be a number + ;; - interpret all values as base 32 + ;; - replace them as if replacing characters in a string + ;; - run luhn + (def digits (split "0123456789")) + (and + (eq? 12 (length value)) + (not (in? (first value) digits)) + (not (in? (first (rest value)) digits)) + (in? (last value) digits) + (luhn? (string->int + (apply concat + (reduce + (lambda (acc val) + (append acc + (->string (try + (string->int val) + (base36-to-base10 val))))) + (split value) (list))))))) diff --git a/rosetta/palindrome.neb b/rosetta/palindrome.neb new file mode 100644 index 0000000..198456d --- /dev/null +++ b/rosetta/palindrome.neb @@ -0,0 +1,6 @@ +(func palindrome? (str) + (branch + ((<= (length str) 1) #true) + ((eq? (first str) (last str)) + (palindrome? (reverse (rest (reverse (rest str)))))) + (#true #false))) diff --git a/rosetta/sum-of-squares.neb b/rosetta/sum-of-squares.neb new file mode 100644 index 0000000..be76194 --- /dev/null +++ b/rosetta/sum-of-squares.neb @@ -0,0 +1,2 @@ +(func sum-of-squares (lst :[:int]) + (reduce + (map (lambda (x) (* x x)) lst) 0)) -- cgit v1.2.3