add reduce, max, project euler #7, some other euler updates
authorcassowarii <cassowary@cassowary.me>
Sun, 12 Jul 2026 22:42:29 +0000 (15:42 -0700)
committercassowarii <cassowary@cassowary.me>
Sun, 12 Jul 2026 22:42:29 +0000 (15:42 -0700)
sample/project_euler/pe01.sa
sample/project_euler/pe03.sa
sample/project_euler/pe04.sa
sample/project_euler/pe05.sa
sample/project_euler/pe06.sa
sample/project_euler/pe07.sa [new file with mode: 0644]
src/lib/method/list.c
src/lib/module/math.c
src/vm/exec.c

index 4b26267..96d3c0f 100644 (file)
@@ -1,11 +1,4 @@
-def sum list {
-  let s = 0
-  list.each => elem {
-    s = s + elem
-  }
-  s
-}
-
-println sum list::iota(1000).filter => num {
-  [3, 5].any? => factor { num %% factor }
-}
+list::iota(1000)
+  | _.filter => num { [3, 5].any? => factor { num %% factor } }
+  | _.reduce 0, => a, b { a + b }
+  | println
index 295bdfc..9336183 100644 (file)
@@ -1,13 +1,3 @@
-def max_positive list {
-  let result = 0
-
-  list.each => element {
-    result = element if element > result
-  }
-
-  result
-}
-
 def factors num {
   let list = []
   let candidate = 2
@@ -23,4 +13,7 @@ def prime? num {
   factors(num).length() == 0
 }
 
-println max_positive factors(600851475143).filter => num { prime? num }
+factors 600851475143
+  | _.filter(prime?)
+  | _.reduce(0, math::max)
+  | println
index 48bd320..5e7b242 100644 (file)
@@ -1,6 +1,5 @@
 def is_palindrome num {
-  let string_num = num | string::from
-  string_num == string_num.split().reverse().join()
+  string::from num | _ == _.split().reverse().join()
 }
 
 let max = 0
index b5aed85..eabaf89 100644 (file)
@@ -7,12 +7,4 @@ def gcd a, b {
   }
 }
 
-def lcm nums {
-  let result = 1
-  nums.each => num {
-    result = result * num // gcd(result, num)
-  }
-  result
-}
-
-println lcm list::iota 1, 21
+println list::iota(1, 21).reduce(1, => a, b { a * b // gcd(a, b) })
index 8e2715c..b361aa9 100644 (file)
@@ -1,9 +1,5 @@
 def sum list {
-  let acc = 0
-  list.each => elem {
-    acc = acc + elem
-  }
-  acc
+  list.reduce(0, => a, b { a + b })
 }
 
 def square num {
diff --git a/sample/project_euler/pe07.sa b/sample/project_euler/pe07.sa
new file mode 100644 (file)
index 0000000..2defd66
--- /dev/null
@@ -0,0 +1,24 @@
+# See Project Euler #3
+def factors num {
+  let list = []
+  let candidate = 2
+  let max = math::sqrt num
+  while candidate <= max {
+    list.push candidate if num %% candidate
+    candidate = candidate + 1
+  }
+  list
+}
+
+def prime? num {
+  factors(num).length() == 0
+}
+
+let seen = 0
+let num = 1
+while seen < 10001 {
+  num = num + 1
+  seen = seen + 1 if prime? num
+}
+
+println num
index b9197a6..c55feca 100644 (file)
@@ -9,6 +9,7 @@
 sbCFuncStatus list_each_cfunc(hVm vm, flag init);
 sbCFuncStatus list_map_cfunc(hVm vm, flag init);
 sbCFuncStatus list_filter_cfunc(hVm vm, flag init);
+sbCFuncStatus list_reduce_cfunc(hVm vm, flag init);
 sbCFuncStatus list_any_cfunc(hVm vm, flag init);
 sbCFuncStatus list_all_cfunc(hVm vm, flag init);
 
@@ -101,6 +102,14 @@ static void filter(hVm vm, hV *list, usize num_params) {
   sbVm_call_c_func(vm, list_filter_cfunc);
 }
 
+static void reduce(hVm vm, hV *list, usize num_params) {
+  if (num_params != 2) {
+    PANIC("wrong number of arguments passed to list#reduce");
+  }
+  sbVm_push_immediate(vm, list);
+  sbVm_call_c_func(vm, list_reduce_cfunc);
+}
+
 static void any_p(hVm vm, hV *list, usize num_params) {
   if (num_params != 1) {
     PANIC("wrong number of arguments passed to list#any?");
@@ -126,6 +135,7 @@ void sbList_create_methods(void) {
   REGISTER_METHOD(&g_list_methods, "each", each);
   REGISTER_METHOD(&g_list_methods, "map", map);
   REGISTER_METHOD(&g_list_methods, "filter", filter);
+  REGISTER_METHOD(&g_list_methods, "reduce", reduce);
   REGISTER_METHOD(&g_list_methods, "any?", any_p);
   REGISTER_METHOD(&g_list_methods, "all?", all_p);
 }
@@ -239,6 +249,44 @@ sbCFuncStatus list_filter_cfunc(hVm vm, flag init) {
   }
 }
 
+sbCFuncStatus list_reduce_cfunc(hVm vm, flag init) {
+  if (init) {
+    /* state: list being reduced, index, callback, result */
+    sbVm_request_var_space(vm, 4);
+    hV *iterating_list = sbVm_pop(vm);
+    hV *result = sbVm_pop(vm);
+    hV *reduce_func = sbVm_pop(vm);
+    usize length;
+    sbList_get_value(iterating_list->list, &length);
+    hV index = HVINT(0);
+
+    vm->fp->locals[0] = *iterating_list;
+    vm->fp->locals[1] = index;
+    vm->fp->locals[2] = *reduce_func;
+    vm->fp->locals[3] = *result;
+  } else {
+    /* get result of reduce function */
+    hV *result = sbVm_pop(vm);
+    vm->fp->locals[3] = *result;
+  }
+
+  usize current_index = vm->fp->locals[1].integer++;
+  usize length;
+  hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+  if (current_index < length) {
+    /* put current result and new value on stack, then call callback function */
+    sbVm_push(vm, &vm->fp->locals[3]);
+    sbVm_push(vm, &iter_values[current_index]);
+    sbVm_push_immediate(vm, &HVINT(2));
+    sbVm_call_func(vm, &vm->fp->locals[2]);
+    return CFUNC_NEXT;
+  } else {
+    /* return result */
+    sbVm_push_immediate(vm, &vm->fp->locals[3]);
+    return CFUNC_END;
+  }
+}
+
 sbCFuncStatus list_any_cfunc(hVm vm, flag init) {
   if (init) {
     /* state: list being filtered, index, callback */
index c04e32c..b9f5599 100644 (file)
@@ -5,6 +5,7 @@
 #include "data/string.h"
 #include "data/symbol.h"
 #include "data/integer.h"
+#include "vm/operations.h"
 #include "vm/exec.h"
 
 #include <math.h>
@@ -29,7 +30,21 @@ static void sbsqrt(hVm vm, usize argc) {
   sbVm_push_immediate(vm, &HVFLOAT(sqrt(original_value)));
 }
 
+static void sbmax(hVm vm, usize argc) {
+  hV *result = &HVNIL;
+  while (argc > 0) {
+    argc --;
+    hV *val = sbVm_pop(vm);
+    if (result->type == IT_NIL || sbV_le(result, val).boolean) {
+      result = val;
+    }
+  }
+
+  sbVm_push_immediate(vm, result);
+}
+
 void sbLib_loadmodule_math() {
   sbLibTable_initialize(&g_math_module, 16, FALSE);
   REGISTER_VALUE(&g_math_module, "sqrt", &HVBUILTIN(sbsqrt));
+  REGISTER_VALUE(&g_math_module, "max", &HVBUILTIN(sbmax));
 }
index 9f8639a..9b8ac03 100644 (file)
@@ -7,6 +7,7 @@
 #include "lib/lib.h"
 
 void call_block(hVm vm, usize block_id, hClosure closure);
+void call_builtin(hVm vm, hV *to_call);
 void return_from_block(hVm vm);
 void execute_instruction(hVm vm);
 void push_stack(hVm vm, hV *value);
@@ -79,7 +80,11 @@ void sbVm_swap(hVm vm) {
 }
 
 void sbVm_call_func(hVm vm, hV *func) {
-  call_block(vm, func->type, func->closure);
+  if (func->type == IT_BUILTIN) {
+    call_builtin(vm, func);
+  } else {
+    call_block(vm, func->type, func->closure);
+  }
 }
 
 void sbVm_transfer_to_func(hVm vm, hV *func) {