Skip to content

Commit 0fd8ffe

Browse files
authored
Add Zeckendorf in m4 (#5345)
1 parent 91bb091 commit 0fd8ffe

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

archive/m/m4/zeckendorf.m4

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
divert(-1)
2+
define(`show_usage',
3+
`Usage: please input a non-negative integer
4+
m4exit(`1')')
5+
6+
dnl is_valid(n)
7+
define(`is_valid', `eval(regexp(`$1', `^\s*-?[0-9]+\s*$') >= 0)')
8+
9+
dnl Reference: https://www.gnu.org/software/m4/manual/m4.html#index-array
10+
dnl array_get(var_name, idx)
11+
define(`array_get', `defn(format(``%s[%s]'', `$1', `$2'))')
12+
13+
dnl array_set(var_name, idx, value)
14+
define(`array_set', `define(format(``%s[%s]'', `$1', `$2'), `$3')')
15+
16+
dnl show_int_list(varname):
17+
dnl for i = 0 to varname["length"] - 1:
18+
dnl if i > 0:
19+
dnl Output ", "
20+
dnl Output varname[i]
21+
define(`show_int_list', `_show_int_list(`$1', 0)')
22+
define(`_show_int_list',
23+
`ifelse(eval(`$2' < array_get(`$1', `length')), 1,
24+
`ifelse(eval(`$2' > 0), 1, `, ')dnl
25+
array_get(`$1', `$2')`'dnl
26+
_show_int_list(`$1', incr($2))'`'dnl
27+
)'dnl
28+
)
29+
30+
dnl fibonacci(value, result_varname):
31+
dnl a = 1
32+
dnl b = 2
33+
dnl result_varname["length"] = 0
34+
dnl while a <= value:
35+
dnl result_varname[result_varname["length"]] = a
36+
dnl result_varname["length"] = result_varname["length"] + 1
37+
dnl a, b = b, a + b
38+
define(`fibonacci',
39+
`array_set(`$2', `length', 0)dnl
40+
_fibonacci(`$1', `$2', 1, 2)'dnl
41+
)
42+
43+
dnl value=$1, result_varname=$2, a=$3, b=$4
44+
define(`_fibonacci',
45+
`ifelse(eval(`$3' <= `$1'), 1,
46+
`array_set(`$2', array_get(`$2', `length'), `$3')dnl
47+
array_set(`$2', `length', eval(incr(array_get(`$2', `length'))))dnl
48+
_fibonacci(`$1', `$2', `$4', eval(`$3 + $4'))'dnl
49+
)'dnl
50+
)
51+
52+
dnl zeckendorf(value, fibs_varname, zecks_varname)
53+
dnl fibonacci(value, fibs_varname)
54+
dnl zecks_varname["length"] = 0
55+
dnl n = fibs_varname["length"] - 1
56+
dnl while n >= 0 and value > 0:
57+
dnl if fibs_varname[n] >= value:
58+
dnl zecks_varname[zecks_varname["length"]] = fibs_varname[n]
59+
dnl zecks_varname["length"] = zecks_varname["length"] + 1
60+
dnl value = value - fibs_varname[n]
61+
dnl n = n - 2
62+
dnl else:
63+
dnl n = n - 1
64+
define(`zeckendorf',
65+
`fibonacci(`$1', `$2')dnl
66+
array_set(`$3', `length', 0)dnl
67+
_zeckendorf(`$1', `$2', `$3', decr(array_get(`$2', `length')))dnl
68+
'dnl
69+
)
70+
71+
dnl value=$1, fibs_varname=$2, zecks_varname=$3, n=$4
72+
define(`_zeckendorf',
73+
`ifelse(eval(`$4' >= 0 && `$1' > 0), 1,
74+
`ifelse(eval(array_get(`$2', `$4') <= `$1'), 1,
75+
`array_set(`$3', array_get(`$3', `length'), array_get(`$2', `$4'))dnl
76+
array_set(`$3', `length', incr(array_get(`$3', `length')))dnl
77+
_zeckendorf(eval(`$1' - array_get(`$2', `$4')), `$2', `$3', eval(`$4' - 2))dnl
78+
',dnl
79+
`_zeckendorf(`$1', `$2', `$3', decr(`$4'))'dnl
80+
)'dnl
81+
)'dnl
82+
)
83+
84+
divert(0)dnl
85+
ifelse(eval(ARGC < 1 || len(ARGV1) < 1 || !is_valid(ARGV1)), 1, `show_usage()')dnl
86+
ifelse(eval(ARGV1 < 0), 1, `show_usage()')dnl
87+
zeckendorf(ARGV1, `fibs', `zecks')dnl
88+
show_int_list(`zecks')

0 commit comments

Comments
 (0)