aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2023-06-03 20:22:18 +0000
committermryouse2023-06-03 20:22:18 +0000
commit7b7bf727da3250907284368b98b0083a4b4e2386 (patch)
tree34802caea5181dc0fb97992746ab99b080448418
initial commit
-rw-r--r--README.md34
-rw-r--r--aoc/2021/day01/input.txt2000
-rw-r--r--aoc/2021/day01/part1.neb55
-rw-r--r--aoc/2021/day01/part2.neb19
-rw-r--r--aoc/2021/day02/input.txt6
-rw-r--r--aoc/2021/day02/part1.neb44
-rw-r--r--aoc/2021/day03/input.txt12
-rw-r--r--aoc/2021/day03/part1.neb73
-rw-r--r--aoc/2021/day04/input.txt19
-rw-r--r--aoc/2021/day04/part01.neb101
-rw-r--r--p99/p01.neb5
-rw-r--r--p99/p02.neb8
-rw-r--r--p99/p03.neb10
-rw-r--r--p99/p04.neb5
-rw-r--r--p99/p05.neb5
-rw-r--r--p99/p06.neb23
-rw-r--r--p99/p07.neb57
-rw-r--r--p99/p08.neb57
-rw-r--r--p99/p09.neb31
-rw-r--r--p99/p10.neb15
-rw-r--r--p99/p11.neb25
-rw-r--r--p99/p12.neb37
-rw-r--r--p99/p13.neb30
-rw-r--r--p99/p14.neb15
-rw-r--r--p99/p15.neb17
-rw-r--r--p99/p16.neb19
-rw-r--r--p99/p17.neb17
-rw-r--r--p99/p18.neb27
-rw-r--r--p99/p19.neb15
-rw-r--r--p99/p20.neb21
-rw-r--r--p99/p21.neb16
-rw-r--r--rosetta/factors-of-int.neb41
-rw-r--r--rosetta/lev.neb20
-rw-r--r--rosetta/lines.neb16
-rw-r--r--rosetta/luhn.neb73
-rw-r--r--rosetta/palindrome.neb6
-rw-r--r--rosetta/sum-of-squares.neb2
37 files changed, 2976 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..26a1120
--- /dev/null
+++ b/README.md
@@ -0,0 +1,34 @@
+# neb examples
+
+Some examples of neb code, using well known and/or widely available problems.
+
+**All examples should be runnable with the latest neb-python interpreter.**
+As the compiler (neb-d) matures, it should be able to run more and more of
+these examples.
+
+The purpose of this repo is two-fold:
+1. Provide working examples to anyone (including my future self) who is
+interested in writing *scare-quotes* ideomatic neb.
+2. By working through examples, locate the rough edges of the language
+(where do things not work/look-or-feel wrong), and use that to *refine* the
+language (both the core syntax and available functions in a standard lib).
+
+## is this really ideomatic neb?
+
+I mean, I don't have a PEP20/PEP8-esque reference document, but this is probably
+as close as things get to ideomatic at this point. Also, as the language
+changes for whatever reason(s), so too will some of the styles (both to
+accomodate breaking changes, and to take advantage of new formats). I also
+try to make comments around bits of code I find particularly clunky, so those
+areas are probably the most likely to change.
+
+## dude, your code is bad...
+
+I'm sure you're right! I'd love to hear any specific feedback on either the
+language or the code written in it. I am not the World's Best Coder by any
+stretch, and so am very open to learning new things and rectifying my mistakes!
+
+## key to examples
+ - `aoc`: [Advent of Code](https://adventofcode.com)
+ - `p99`: [Ninety-Nine Lisp Problems](https://www.ic.unicamp.br/~meidanis/courses/mc336/problemas-lisp/L-99_Ninety-Nine_Lisp_Problems.html)
+ - `rosetta`: [Rosetta Code](https://rosettacode.org/wiki/Rosetta_Code) (Note: the names of the problems don't line up well)
diff --git a/aoc/2021/day01/input.txt b/aoc/2021/day01/input.txt
new file mode 100644
index 0000000..b3ee114
--- /dev/null
+++ b/aoc/2021/day01/input.txt
@@ -0,0 +1,2000 @@
+198
+208
+209
+212
+213
+217
+218
+223
+222
+224
+216
+233
+238
+239
+240
+250
+263
+264
+267
+274
+288
+316
+319
+330
+340
+347
+349
+354
+350
+349
+351
+352
+353
+371
+383
+385
+405
+413
+455
+451
+459
+458
+459
+461
+463
+475
+480
+486
+489
+497
+502
+512
+513
+516
+517
+528
+559
+560
+558
+565
+566
+567
+571
+573
+574
+582
+583
+585
+589
+597
+608
+607
+614
+619
+608
+624
+665
+666
+675
+695
+698
+703
+711
+733
+738
+739
+742
+743
+763
+775
+778
+804
+806
+810
+812
+818
+819
+828
+867
+866
+876
+878
+881
+875
+881
+858
+859
+868
+869
+860
+888
+890
+891
+893
+894
+919
+924
+925
+933
+937
+950
+955
+966
+984
+989
+993
+996
+997
+1015
+1031
+1035
+1039
+1055
+1057
+1058
+1059
+1060
+1061
+1067
+1069
+1070
+1059
+1060
+1077
+1079
+1078
+1080
+1087
+1088
+1090
+1097
+1082
+1102
+1105
+1106
+1120
+1125
+1130
+1132
+1154
+1141
+1135
+1131
+1133
+1134
+1137
+1138
+1141
+1142
+1143
+1166
+1175
+1193
+1201
+1236
+1238
+1234
+1240
+1242
+1243
+1271
+1276
+1277
+1272
+1286
+1288
+1290
+1292
+1317
+1341
+1361
+1363
+1375
+1376
+1377
+1383
+1387
+1390
+1402
+1404
+1412
+1418
+1426
+1429
+1466
+1480
+1483
+1478
+1484
+1486
+1488
+1491
+1486
+1489
+1492
+1517
+1520
+1523
+1539
+1546
+1551
+1521
+1517
+1518
+1522
+1525
+1526
+1539
+1540
+1544
+1545
+1561
+1571
+1572
+1574
+1575
+1568
+1573
+1587
+1588
+1600
+1603
+1627
+1629
+1633
+1645
+1670
+1671
+1685
+1690
+1696
+1698
+1703
+1698
+1699
+1702
+1714
+1716
+1709
+1738
+1753
+1761
+1766
+1769
+1772
+1761
+1763
+1774
+1781
+1782
+1799
+1802
+1816
+1818
+1819
+1805
+1810
+1817
+1819
+1831
+1834
+1835
+1852
+1855
+1858
+1859
+1856
+1857
+1868
+1885
+1891
+1893
+1890
+1891
+1892
+1893
+1896
+1911
+1912
+1914
+1916
+1914
+1918
+1930
+1932
+1958
+1966
+1976
+1982
+1985
+1986
+1987
+1992
+1997
+2031
+2041
+2042
+2044
+2058
+2060
+2075
+2073
+2084
+2087
+2090
+2125
+2128
+2129
+2130
+2131
+2136
+2137
+2145
+2150
+2152
+2155
+2161
+2162
+2165
+2167
+2189
+2197
+2199
+2214
+2226
+2233
+2234
+2241
+2242
+2256
+2259
+2263
+2257
+2267
+2270
+2269
+2272
+2273
+2275
+2279
+2284
+2285
+2266
+2271
+2287
+2291
+2310
+2313
+2314
+2317
+2311
+2312
+2311
+2312
+2326
+2331
+2332
+2338
+2340
+2352
+2355
+2360
+2361
+2357
+2371
+2384
+2380
+2392
+2393
+2396
+2397
+2400
+2417
+2420
+2421
+2422
+2444
+2457
+2458
+2464
+2467
+2494
+2495
+2498
+2510
+2514
+2521
+2526
+2525
+2533
+2536
+2547
+2544
+2547
+2556
+2557
+2558
+2561
+2570
+2571
+2573
+2575
+2583
+2584
+2585
+2572
+2574
+2575
+2587
+2589
+2590
+2602
+2603
+2604
+2605
+2589
+2603
+2608
+2611
+2616
+2613
+2617
+2618
+2619
+2628
+2629
+2630
+2631
+2639
+2645
+2649
+2657
+2665
+2673
+2680
+2679
+2680
+2702
+2703
+2709
+2711
+2714
+2715
+2716
+2715
+2721
+2720
+2739
+2745
+2748
+2752
+2749
+2748
+2749
+2751
+2752
+2750
+2760
+2777
+2778
+2779
+2780
+2787
+2800
+2805
+2810
+2812
+2820
+2821
+2843
+2846
+2853
+2862
+2861
+2867
+2880
+2890
+2891
+2892
+2885
+2887
+2890
+2894
+2897
+2925
+2926
+2931
+2933
+2940
+2943
+2941
+2959
+2971
+2982
+2984
+3002
+3006
+3008
+3012
+3013
+3034
+3043
+3059
+3063
+3064
+3060
+3075
+3090
+3091
+3104
+3108
+3114
+3117
+3106
+3104
+3110
+3113
+3114
+3126
+3119
+3138
+3140
+3141
+3143
+3139
+3145
+3147
+3153
+3161
+3170
+3168
+3180
+3181
+3177
+3196
+3210
+3216
+3232
+3233
+3234
+3235
+3239
+3240
+3242
+3243
+3244
+3243
+3248
+3249
+3275
+3276
+3278
+3280
+3286
+3291
+3293
+3294
+3301
+3310
+3319
+3326
+3338
+3339
+3348
+3366
+3376
+3371
+3372
+3404
+3407
+3408
+3425
+3444
+3451
+3457
+3452
+3459
+3468
+3491
+3475
+3476
+3481
+3505
+3516
+3519
+3542
+3543
+3541
+3542
+3541
+3551
+3553
+3552
+3533
+3542
+3543
+3561
+3562
+3563
+3566
+3571
+3572
+3596
+3600
+3603
+3607
+3608
+3609
+3613
+3654
+3665
+3672
+3661
+3662
+3663
+3670
+3676
+3683
+3707
+3709
+3714
+3717
+3709
+3710
+3713
+3714
+3715
+3716
+3735
+3749
+3763
+3770
+3784
+3782
+3786
+3790
+3792
+3794
+3803
+3805
+3819
+3823
+3826
+3828
+3838
+3839
+3843
+3870
+3877
+3888
+3889
+3891
+3892
+3893
+3894
+3880
+3860
+3878
+3880
+3888
+3893
+3898
+3904
+3906
+3907
+3910
+3918
+3927
+3946
+3973
+3982
+3979
+3980
+3993
+3984
+3988
+3986
+3987
+3988
+3989
+3997
+4000
+4001
+4025
+4030
+4034
+4038
+4040
+4044
+4046
+4048
+4057
+4067
+4079
+4092
+4094
+4122
+4124
+4128
+4127
+4128
+4132
+4136
+4141
+4146
+4151
+4153
+4163
+4167
+4168
+4170
+4172
+4176
+4177
+4178
+4194
+4198
+4199
+4201
+4203
+4204
+4205
+4204
+4209
+4211
+4213
+4224
+4240
+4242
+4255
+4266
+4280
+4284
+4295
+4310
+4323
+4343
+4351
+4359
+4383
+4387
+4388
+4397
+4401
+4403
+4404
+4405
+4425
+4431
+4435
+4439
+4444
+4452
+4461
+4470
+4466
+4467
+4469
+4481
+4482
+4498
+4496
+4504
+4505
+4512
+4518
+4520
+4521
+4523
+4534
+4516
+4527
+4525
+4534
+4535
+4551
+4565
+4570
+4571
+4578
+4584
+4595
+4609
+4610
+4618
+4628
+4629
+4630
+4634
+4636
+4637
+4640
+4659
+4664
+4669
+4665
+4673
+4687
+4688
+4693
+4694
+4697
+4667
+4678
+4679
+4702
+4707
+4706
+4709
+4711
+4718
+4725
+4716
+4718
+4723
+4724
+4726
+4727
+4729
+4735
+4736
+4738
+4739
+4758
+4763
+4773
+4774
+4776
+4777
+4778
+4777
+4785
+4786
+4771
+4773
+4774
+4777
+4781
+4783
+4788
+4791
+4794
+4807
+4816
+4818
+4825
+4828
+4838
+4822
+4831
+4837
+4841
+4851
+4854
+4870
+4876
+4888
+4889
+4900
+4906
+4909
+4910
+4917
+4919
+4920
+4926
+4928
+4934
+4941
+4943
+4945
+4948
+4950
+4956
+4951
+4948
+4954
+4958
+4960
+4959
+4962
+4969
+4982
+4986
+4994
+5000
+5009
+5027
+5025
+5029
+5033
+5037
+5036
+5037
+5040
+5032
+5033
+5034
+5039
+5045
+5050
+5045
+5076
+5077
+5082
+5083
+5106
+5107
+5114
+5117
+5137
+5138
+5143
+5147
+5153
+5156
+5171
+5182
+5183
+5184
+5185
+5189
+5182
+5189
+5194
+5201
+5205
+5213
+5218
+5221
+5223
+5230
+5231
+5243
+5255
+5230
+5228
+5237
+5245
+5248
+5259
+5260
+5272
+5278
+5281
+5287
+5286
+5287
+5298
+5328
+5329
+5333
+5335
+5337
+5339
+5341
+5346
+5349
+5350
+5351
+5358
+5359
+5360
+5374
+5376
+5359
+5360
+5388
+5401
+5406
+5410
+5412
+5413
+5414
+5415
+5435
+5436
+5441
+5443
+5448
+5446
+5448
+5449
+5464
+5465
+5466
+5469
+5470
+5492
+5493
+5494
+5509
+5520
+5528
+5530
+5537
+5541
+5542
+5559
+5562
+5563
+5588
+5595
+5596
+5601
+5618
+5626
+5627
+5641
+5667
+5679
+5685
+5693
+5695
+5717
+5733
+5734
+5754
+5755
+5757
+5758
+5759
+5760
+5761
+5771
+5774
+5780
+5784
+5785
+5787
+5788
+5790
+5800
+5811
+5814
+5810
+5811
+5794
+5792
+5803
+5804
+5812
+5814
+5815
+5836
+5852
+5853
+5855
+5878
+5879
+5880
+5883
+5889
+5897
+5911
+5932
+5934
+5935
+5936
+5938
+5939
+5941
+5951
+5955
+5950
+5951
+5954
+5970
+5971
+5974
+5977
+5978
+5985
+5986
+6013
+6024
+6031
+6037
+6043
+6052
+6051
+6053
+6076
+6096
+6101
+6106
+6108
+6115
+6125
+6106
+6107
+6104
+6114
+6142
+6143
+6162
+6169
+6170
+6171
+6181
+6198
+6199
+6202
+6206
+6207
+6244
+6246
+6249
+6250
+6254
+6264
+6271
+6276
+6277
+6268
+6271
+6288
+6293
+6308
+6309
+6326
+6341
+6345
+6344
+6341
+6364
+6365
+6366
+6370
+6371
+6373
+6376
+6377
+6378
+6377
+6379
+6386
+6396
+6397
+6420
+6422
+6429
+6433
+6463
+6472
+6473
+6490
+6491
+6492
+6497
+6522
+6523
+6524
+6519
+6520
+6521
+6525
+6530
+6531
+6534
+6535
+6543
+6552
+6558
+6584
+6586
+6587
+6588
+6606
+6614
+6618
+6646
+6650
+6651
+6654
+6677
+6663
+6665
+6676
+6655
+6653
+6655
+6665
+6667
+6682
+6692
+6703
+6704
+6707
+6715
+6719
+6730
+6731
+6733
+6743
+6747
+6748
+6750
+6759
+6771
+6772
+6776
+6775
+6776
+6782
+6785
+6812
+6841
+6858
+6860
+6859
+6877
+6886
+6895
+6914
+6919
+6922
+6924
+6933
+6935
+6936
+6937
+6938
+6952
+6962
+6965
+6984
+6987
+6986
+6985
+6977
+6967
+6968
+6966
+6980
+6997
+6994
+7002
+7008
+7000
+6975
+7009
+7014
+7015
+7026
+7027
+7034
+7036
+7041
+7040
+7041
+7045
+7048
+7065
+7074
+7075
+7082
+7087
+7092
+7098
+7097
+7111
+7127
+7124
+7135
+7136
+7137
+7140
+7153
+7156
+7158
+7174
+7176
+7177
+7163
+7166
+7159
+7157
+7158
+7164
+7165
+7172
+7190
+7194
+7199
+7200
+7205
+7208
+7207
+7222
+7227
+7244
+7249
+7271
+7272
+7273
+7274
+7281
+7286
+7288
+7314
+7315
+7317
+7318
+7319
+7304
+7307
+7308
+7309
+7312
+7319
+7322
+7337
+7338
+7345
+7346
+7350
+7360
+7361
+7362
+7360
+7395
+7400
+7404
+7405
+7407
+7406
+7411
+7420
+7435
+7440
+7442
+7446
+7453
+7446
+7448
+7467
+7471
+7469
+7470
+7482
+7485
+7492
+7488
+7489
+7492
+7493
+7494
+7497
+7504
+7520
+7525
+7547
+7554
+7543
+7553
+7560
+7561
+7577
+7589
+7591
+7593
+7587
+7596
+7597
+7584
+7590
+7591
+7599
+7626
+7627
+7628
+7630
+7645
+7639
+7645
+7652
+7657
+7662
+7664
+7674
+7680
+7681
+7694
+7698
+7716
+7704
+7705
+7706
+7708
+7712
+7716
+7715
+7717
+7722
+7723
+7728
+7721
+7722
+7724
+7727
+7735
+7737
+7725
+7746
+7747
+7750
+7761
+7762
+7765
+7777
+7780
+7776
+7777
+7778
+7759
+7769
+7770
+7787
+7797
+7798
+7804
+7803
+7804
+7805
+7811
+7825
+7824
+7826
+7827
+7828
+7851
+7867
+7887
+7889
+7890
+7900
+7904
+7917
+7918
+7935
+7941
+7942
+7946
+7947
+7948
+7949
+7976
+7979
+7981
+7983
+7988
+7999
+8000
+8009
+8011
+8012
+8019
+8021
+8025
+8027
+8006
+8011
+8034
+8036
+8037
+8038
+8013
+8024
+8029
+8032
+8033
+8034
+8032
+8034
+8036
+8059
+8060
+8063
+8064
+8081
+8090
+8097
+8122
+8135
+8147
+8149
+8150
+8151
+8162
+8174
+8154
+8158
+8162
+8170
+8171
+8188
+8189
+8190
+8191
+8196
+8205
+8216
+8217
+8222
+8233
+8239
+8240
+8242
+8257
+8249
+8262
+8264
+8274
+8309
+8311
+8328
+8333
+8335
+8338
+8344
+8350
+8349
+8350
+8363
+8366
+8370
+8371
+8395
+8398
+8401
+8410
+8425
+8429
+8430
+8441
+8443
+8445
+8451
+8452
+8455
+8458
+8431
+8443
+8453
+8459
+8477
+8474
+8479
+8476
+8487
+8488
+8489
+8500
+8501
+8503
+8504
+8538
+8523
+8529
+8530
+8556
+8573
+8576
+8589
+8595
+8624
+8632
+8634
+8628
+8636
+8635
+8636
+8644
+8659
+8661
+8641
+8652
+8659
+8650
+8664
+8667
+8674
+8676
+8678
+8686
+8696
+8697
+8735
+8740
+8749
+8767
+8769
+8747
+8751
+8760
+8755
+8766
+8768
+8777
+8782
+8788
+8796
+8799
+8801
+8809
+8807
+8816
+8827
+8831
+8835
+8836
+8843
+8844
+8845
+8851
+8858
+8860
+8862
+8863
+8889
+8891
+8912
+8913
+8924
+8928
+8929
+8939
+8955
+8957
+8958
+8963
+8988
+8989
+8997
+8995
+8999
+8968
+8990
+8991
+8992
+8994
+8996
+9013
+9024
+9026
+9035
+9046
+9047
+9083
+9084
+9089
+9096
+9108
+9107
+9116
+9123
+9122
+9128
+9132
+9151
+9155
+9163
+9174
+9178
+9183
+9199
+9209
+9217
+9219
+9232
+9233
+9232
+9237
+9241
+9244
+9245
+9247
+9251
+9252
+9266
+9285
+9284
+9291
+9294
+9295
+9296
+9300
+9322
+9328
+9333
+9337
+9345
+9346
+9347
+9371
+9375
+9394
+9397
+9404
+9406
+9422
+9425
+9438
+9440
+9435
+9442
+9455
+9473
+9475
+9496
+9499
+9500
+9511
+9512
+9513
+9539
+9540
+9543
+9547
+9550
+9557
+9571
+9577
+9593
+9600
+9609
+9615
+9620
+9621
+9616
+9625
+9626
+9637
+9638
+9642
+9648
+9656
+9654
+9661
+9665
+9696
+9705
+9710
+9719
+9720
+9717
+9718
+9717
+9719
+9724
+9725
+9738
+9741
+9743
+9744
+9745
+9765
+9778
+9779
+9789
+9791
+9773
+9778
+9780
+9782
+9783
+9782
+9797
+9799
+9800
+9801
+9823
+9824
+9834
+9836
+9841
+9845
+9847
+9865
+9868
+9883
+9884
+9887
+9890
+9892
+9899
+9908
+9910
+9911
+9915
+9918
+9922
+9926
+9923
+9944
+9947
+9948
+9949
+9958
+9959
+9961
+9973
+9954
+9976
+9978
+10001
+10000
+9992
+9997
+9985
+9995
+9996
+10005
+9999
+10001
+10002
+10009
+10041
+10045
+10051
+10070
+10071
+10073
+10100
+10099
+10100
+10101
+10102
+10105
+10082
+10083
+10082
+10086
+10112
+10113
+10114
+10122
+10124
+10127
+10140
+10156
+10157
+10158
+10159
+10162
+10163
+10166
+10177
+10178
+10180
+10178
+10179
+10191
+10186
+10198
+10201
+10204
+10227
+10229
+10232
+10234
+10246
+10247
+10248
+10249
+10250
+10269
+10277
+10278
+10279
+10289
+10291
+10294
+10292
+10304
+10324
+10339
+10342
+10343
+10349
+10354
+10371
+10370
+10374
+10376
+10379
+10405
+10406
+10405
+10403
+10411
+10412
+10411
+10419
+10422
+10435
+10437
+10438
+10437
+10440
+10427
+10421
+10432
+10434
+10439
+10449
+10442
+10469
+10471
+10476
+10480
+10481
+10485
+10507
+10508
+10511
+10512
+10513
+10523
+10524
+10529
+10536
+10552
+10563
+10569
+10573
+10575
+10576
+10578
+10596
+10602
+10630
+10647
+10657
+10659
+10684
+10687
+10692
+10693
+10700
+10702
+10703
+10709
+10714
+10716
+10727
+10746
+10744
+10754
+10753
+10754
+10755
+10759
+10763
+10764
+10765
+10769
+10770
+10771
+10777
+10796
+10807
+10813
+10818
+10825
+10830
+10835
+10836
+10849
+10858
+10873
+10882
+10879
+10882
+10886
+10902
+10903
+10931
+10930
diff --git a/aoc/2021/day01/part1.neb b/aoc/2021/day01/part1.neb
new file mode 100644
index 0000000..066a86d
--- /dev/null
+++ b/aoc/2021/day01/part1.neb
@@ -0,0 +1,55 @@
+;; https://adventofcode.com/2021/day/1
+
+; this feels more lisp-y
+; maximum recursion depth reached quickly (in neb-python)
+(func increase-count-recur (inp acc)
+ (branch
+ ((eq? 0 (length (rest inp))) acc)
+ ((> (first (rest inp)) (first inp))
+ (increase-count-recur (rest inp) (+ 1 acc)))
+ (#true
+ (increase-count-recur (rest inp) acc))))
+
+; this works, but i don't like redefining variables
+(func increase-count-iter (inp)
+ (def acc 0)
+ (def prev (first inp))
+ (for-each (rest inp)
+ (if (> _item_ prev)
+ (redef acc (+ 1 acc)))
+ (redef prev _item_))
+ acc)
+
+; (a b c d e) => ((a b) (b c) (c d) (d e))
+(func pairwise (inp)
+ (zip (most inp) (rest inp)))
+
+(func abs (num)
+ (if (< num 0)
+ (* (- 1) num)
+ num))
+
+(func list-subtract (lst)
+ (def ret (apply - lst))
+ (- (/ (abs ret) ret) 1))
+
+; this algorithm is very roundabout
+(func increase-count-iter-2 (inp)
+ (abs (/ (apply + (map list-subtract (pairwise inp))) 2)))
+
+; this is the most ideomatic
+(func increase-count (inp)
+ (length
+ (filter
+ (lambda (x) (apply < x))
+ (pairwise inp))))
+
+(def lines
+ (map string->int
+ (map strip
+ (read-lines "input.txt"))))
+
+;(print (->string (increase-count-recur lines 0)))
+(print (->string (increase-count-iter lines)))
+(print (->string (increase-count-iter-2 lines)))
+(print (->string (increase-count lines)))
diff --git a/aoc/2021/day01/part2.neb b/aoc/2021/day01/part2.neb
new file mode 100644
index 0000000..31e3c99
--- /dev/null
+++ b/aoc/2021/day01/part2.neb
@@ -0,0 +1,19 @@
+; return 1 if next three greater than first three
+(func is-increasing (inp)
+ (if (< (apply + (most inp)) (apply + (rest inp)))
+ 1
+ 0))
+
+; this works, but i don't like redefining variables
+(func iter-list (inp)
+ (def acc 0)
+ (for-count (- (length inp) 3)
+ (redef acc (+ acc (is-increasing (slice inp _idx_ 4)))))
+ acc)
+
+(def lines
+ (map string->int
+ (map strip
+ (read-lines "input.txt"))))
+
+(print (->string (iter-list lines)))
diff --git a/aoc/2021/day02/input.txt b/aoc/2021/day02/input.txt
new file mode 100644
index 0000000..b7172ac
--- /dev/null
+++ b/aoc/2021/day02/input.txt
@@ -0,0 +1,6 @@
+forward 5
+down 5
+forward 8
+up 3
+down 8
+forward 2
diff --git a/aoc/2021/day02/part1.neb b/aoc/2021/day02/part1.neb
new file mode 100644
index 0000000..82201ab
--- /dev/null
+++ b/aoc/2021/day02/part1.neb
@@ -0,0 +1,44 @@
+;; https://adventofcode.com/2021/day/2
+
+; optional -- 'sum' is more visually indicative than 'apply +'
+(func sum (nums) (apply + nums))
+
+(func do-the-thing (inp)
+ ; order doesn't matter, so we can split horizontal and vertical
+ ; movement without affecting the answer
+ (def vert-changes (filter (lambda (x) (in? (first x) (list "up" "down"))) inp))
+ (def horiz-changes (filter (lambda (x) (eq? (first x) "forward")) inp))
+
+ ; turn "up"/"down" into +/- 1
+ (def vert-numbers
+ (map
+ (lambda (x)
+ (if (eq? (first x) "up")
+ (prepend (rest x) (- 1))
+ (prepend (rest x) 1)))
+ vert-changes))
+
+ (def vert
+ (sum ; add everything up
+ (map
+ (lambda (x) (* (first x) (last x))) ; multiply each pair together
+ vert-numbers)))
+
+ (def horiz
+ (sum
+ (map last horiz-changes))) ; we know there's only 2 elements in each list, and we want the last one
+
+ (print (concat "vert: " (->string vert)))
+ (print (concat "horiz: " (->string horiz)))
+ (* vert horiz))
+
+(def lines
+ (map
+ (lambda (x) (list (first x) (string->int (first (rest x))))) ; convert second values to int
+ (map
+ (lambda (x) (split x " "))
+ (map strip
+ (read-lines "input.txt")))))
+
+(print (->string lines))
+(print (->string (do-the-thing lines)))
diff --git a/aoc/2021/day03/input.txt b/aoc/2021/day03/input.txt
new file mode 100644
index 0000000..a6366a8
--- /dev/null
+++ b/aoc/2021/day03/input.txt
@@ -0,0 +1,12 @@
+00100
+11110
+10110
+10111
+10101
+01111
+00111
+11100
+10000
+11001
+00010
+01010
diff --git a/aoc/2021/day03/part1.neb b/aoc/2021/day03/part1.neb
new file mode 100644
index 0000000..7ca6a08
--- /dev/null
+++ b/aoc/2021/day03/part1.neb
@@ -0,0 +1,73 @@
+;; https://adventofcode.com/2021/day/3
+
+(func one-most-common (inp)
+ (>
+ (length
+ (filter (lambda (x) (eq? "1" x)) inp))
+ (/ (length inp) 2)))
+
+; treating bits as a string of 1s and 0s
+; note: for this problem, even if neb had byte things,
+; strings would probably still be the way to go
+(func bit-flip (bitstr)
+ (join
+ (map
+ (lambda (x) (if (eq? "0" x) "1" "0"))
+ (split bitstr))
+ ""))
+
+; 'exp' or something should be in the stdlib
+(func two-n (n)
+ (branch
+ ((eq? 0 n) 1)
+ ((eq? 1 n) 2)
+ (#true
+ (* 2 (two-n (- n 1))))))
+
+(func parse-binary (bitstr)
+ (parse-binary bitstr 0 0))
+
+(func parse-binary (bitstr pos acc)
+ (if (eq? 0 (length bitstr))
+ acc
+ (block
+ (def next-int (string->int (last bitstr)))
+ (if (eq? 0 next-int)
+ (parse-binary
+ (most bitstr)
+ (+ 1 pos)
+ acc)
+ (parse-binary
+ (most bitstr)
+ (+ 1 pos)
+ (+ acc
+ (two-n pos)))))))
+ ;(* 2 pos)))))))
+
+(func do-the-thing (inp)
+ ; i don't like the def/redef pattern
+ ; this would benefit from something like "gather"
+ ; this might also work as a map/reduce?
+ (def out "")
+ (for-count (length (first inp))
+ (def one?
+ (one-most-common
+ (map
+ (lambda (x)
+ (first (slice x _idx_ 1)))
+ inp)))
+ (redef out
+ (concat out
+ (if one? "1" "0"))))
+ (print (->string
+ (*
+ (parse-binary out)
+ (parse-binary (bit-flip out)))))
+ )
+
+(def lines
+ (map split ; get all numbers as list of chars
+ (map strip
+ (read-lines "input.txt"))))
+
+(do-the-thing lines)
diff --git a/aoc/2021/day04/input.txt b/aoc/2021/day04/input.txt
new file mode 100644
index 0000000..669a51d
--- /dev/null
+++ b/aoc/2021/day04/input.txt
@@ -0,0 +1,19 @@
+7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
+
+22 13 17 11 0
+ 8 2 23 4 24
+21 9 14 16 7
+ 6 10 3 18 5
+ 1 12 20 15 19
+
+ 3 15 0 2 22
+ 9 18 13 17 5
+19 8 7 25 23
+20 11 10 24 4
+14 21 16 12 6
+
+14 21 17 24 4
+10 16 15 9 19
+18 8 23 26 20
+22 11 13 6 5
+ 2 0 12 3 7
diff --git a/aoc/2021/day04/part01.neb b/aoc/2021/day04/part01.neb
new file mode 100644
index 0000000..49b4a7a
--- /dev/null
+++ b/aoc/2021/day04/part01.neb
@@ -0,0 +1,101 @@
+;; https://adventofcode.com/2021/day/4
+
+; good candidate for loop-acc
+(func get-all-boards (inp)
+ (def ret (list))
+ (for-count (/ (length inp) 5)
+ (redef ret (append ret
+ (get-board (slice inp (+ (* 5 (- _idx_ 1)) 1) 5)))))
+ ret)
+
+(func get-board (inp)
+ (map get-row inp))
+
+; each row is a string of items
+; separated by (potentially) several spaces
+; return a list of just the strings
+(func get-row (row)
+ (filter
+ (lambda (x)
+ (not (eq? "" x)))
+ (split row " ")))
+
+
+(func process-boards (inp)
+ (def raw-boards
+ (filter
+ (lambda (x) (not (eq? "" x)))
+ inp))
+ (get-all-boards raw-boards))
+
+(def lines
+ (map strip
+ (read-lines "input.txt")))
+
+(def moves (split (first lines) ",")) ; moves is the first line
+(def boards (process-boards (rest lines)))
+
+; this is a helper to work with zippers
+; probably good to have in the stdlib
+(func unzip (lst idx)
+ (list
+ (reverse
+ (slice lst 1 idx))
+ (slice lst (+ 1 idx))))
+
+(func has-won-row (row)
+ (apply and row))
+
+(func has-won (board moves)
+ (def checked (check-board board moves))
+ (def winner #false)
+
+ ; check rows
+ ; no break statement means we have to check everything,
+ ; even after a winner is found
+ ; can also use a while, but that would require more redefs
+ (for-each checked
+ (if (has-won-row _item_)
+ (redef winner #true)))
+
+ ; no break here means we check columns even if we won on rows
+
+ ; check columns
+ (for-count 5
+ (if (has-won-row
+ (map
+ (lambda (x) (first (slice x _idx_ 1)))
+ checked))
+ (redef winner #true)))
+
+ winner)
+
+
+(func check-board (board moves)
+ (func check-row (row)
+ (map
+ (lambda (x)
+ (in? x moves))
+ row))
+ (map check-row board))
+
+
+; how do we better iterate through this list?
+; called/next would be perfect for a zipper
+(def cur (list (list) moves)) ; init zip
+(def winner #false)
+(while (not winner)
+ (redef cur (unzip moves (+ 1 (length (first cur)))))
+ (print (->string cur))
+ (print (->string
+ (map
+ (lambda (x) (has-won x (first cur)))
+ boards)))
+ ;(def checked (check-board (first boards) (first cur)))
+ ;(print (->string checked))
+ (if (nil? (last cur))
+ (redef winner #true))
+ )
+
+(print (->string moves))
+;(print (->string (unzip moves 2)))
diff --git a/p99/p01.neb b/p99/p01.neb
new file mode 100644
index 0000000..e50cfe7
--- /dev/null
+++ b/p99/p01.neb
@@ -0,0 +1,5 @@
+; P01 Find the last box of a list.
+
+(def a (list "a" "b" "c" "d"))
+
+(print (last a))
diff --git a/p99/p02.neb b/p99/p02.neb
new file mode 100644
index 0000000..317674e
--- /dev/null
+++ b/p99/p02.neb
@@ -0,0 +1,8 @@
+; P02 - Find the last two elements of a list.
+
+(def a (list "a" "b" "c" "d"))
+
+; slice takes the index (1-based) to begin
+; and, optionally, the length of the slice
+; (when missing, will grab until the end)
+(print (->string (slice a (- (length a) 1))))
diff --git a/p99/p03.neb b/p99/p03.neb
new file mode 100644
index 0000000..05e0457
--- /dev/null
+++ b/p99/p03.neb
@@ -0,0 +1,10 @@
+; P03 - Find the K'th element of a list.
+; The first element in the list is number 1.
+
+(def a (list "a" "b" "c" "d"))
+
+(func kth (lst k)
+ (first (slice lst k 1))) ; since slice returns a list, get the element with first
+
+(print (kth a 3))
+;(kth a 8) ; panic! there is no 8th element
diff --git a/p99/p04.neb b/p99/p04.neb
new file mode 100644
index 0000000..544dc00
--- /dev/null
+++ b/p99/p04.neb
@@ -0,0 +1,5 @@
+; P04 - Find the number of elements of a list
+
+(def a (list "a" "b" "c" "d"))
+
+(print (->string (length a)))
diff --git a/p99/p05.neb b/p99/p05.neb
new file mode 100644
index 0000000..b04e329
--- /dev/null
+++ b/p99/p05.neb
@@ -0,0 +1,5 @@
+; P05 - Reverse a list
+
+(def a (list "a" "b" "c" "d"))
+
+(print (->string (reverse a)))
diff --git a/p99/p06.neb b/p99/p06.neb
new file mode 100644
index 0000000..f219058
--- /dev/null
+++ b/p99/p06.neb
@@ -0,0 +1,23 @@
+; P06 Find out whether a list is a palindrome.
+; A palindrome can be read forward or backward; e.g. (x a m a x).
+
+(def odd-good (list "x" "a" "m" "a" "x")) ; odd number of elements (good)
+(def odd-bad (list "x" "f" "m" "a" "x")) ; odd number of elements (bad)
+(def even-good (list "a" "b" "b" "a")) ; even number of elements (good)
+(def even-bad (list "a" "b" "b" "f")) ; even number of elements (bad)
+(def single (list "a")) ; single element
+(def empty (list))
+
+(func palindrome? (lst) ; by convention, funcs returning :bool end with a ?
+ (if (< (length lst) 2) ; 0 or 1 element lists are palindromic
+ #true
+ (and
+ (eq? (first lst) (last lst)) ; first element and last element are equal
+ (palindrome? (most (rest lst)))))) ; this would be clearer if slices supported negative numbers
+
+(print (->string (palindrome? odd-good)))
+(print (->string (palindrome? odd-bad)))
+(print (->string (palindrome? even-good)))
+(print (->string (palindrome? even-bad)))
+(print (->string (palindrome? single)))
+(print (->string (palindrome? empty)))
diff --git a/p99/p07.neb b/p99/p07.neb
new file mode 100644
index 0000000..9eee9ef
--- /dev/null
+++ b/p99/p07.neb
@@ -0,0 +1,57 @@
+; P07 Flatten a nested array structure.
+; Transform an array, possibly holding arrays as elements into a `flat'
+; list by replacing each array with its elements (recursively).
+
+(def a (list "a" (list "b" (list "c" "d") "e")))
+
+; this belongs in stdlib
+(func extend (lst1 lst2)
+ (reduce append lst2 lst1))
+
+; can overload functions of different arities
+(func flatten-iter (item)
+ (flatten-iter item (list)))
+
+; iterative solution
+(func flatten-iter (item acc)
+ (branch
+ ((eq? (typeof item) :[:any])
+ (if (empty? item)
+ acc
+ (flatten-iter (rest item) (extend acc (flatten-iter (first item))))))
+ (#true
+ (append acc item))))
+
+; we can also use the type system/dynamic dispatch to split up the work
+(func flatten-typ (item)
+ (flatten-typ item (list)))
+
+; non-empty lists
+(func flatten-typ (lst :{:any} acc)
+ (flatten-typ (rest lst) (extend acc (flatten-typ (first lst)))))
+
+; empty lists
+(func flatten-typ (lst :nil acc)
+ acc)
+
+; other things
+; note: we would need to know what type(s) is inside the list to avoid an
+; ambiguous definition
+;(func flatten-typ (item :string acc)
+; (append acc item))
+
+; this might be clearer/more flexible
+; maybe "not this type" should be a thing, like :![:any]
+(func not-a-list? (item)
+ (not (eq? (typeof item) :[:any])))
+
+(type :not-a-list :any not-a-list?) ; should be able to pass a lambda
+
+; this handles anything that's not a list
+(func flatten-typ (item :not-a-list acc)
+ (append acc item))
+
+(print (->string a))
+(print (->string (flatten-iter a)))
+(print (->string a))
+(print (->string (flatten-typ a)))
diff --git a/p99/p08.neb b/p99/p08.neb
new file mode 100644
index 0000000..5df816f
--- /dev/null
+++ b/p99/p08.neb
@@ -0,0 +1,57 @@
+; P08 Eliminate consecutive duplicates of list elements.
+; If a list contains repeated elements they should be replaced with a
+; single copy of the element. The order of the elements should not be changed.
+
+(def a (list "a" "a" "a" "a" "b" "c" "c" "a" "a" "d" "e" "e" "e" "e"))
+
+(func compress-iter (lst)
+ (def out (list))
+ (for-each lst
+ (if (or (empty? out)
+ (not (eq? _item_ (last out))))
+ (redef out (append out _item_))))
+ out)
+
+; use the type system/dynamic dispatch
+(func compress-typ (lst)
+ (compress-typ lst (list)))
+
+; empty lists
+(func compress-typ (lst :nil acc)
+ acc)
+
+; non-empty lists, combined with a branch
+;(func compress-typ (lst :{:any} acc)
+; (branch
+; ((empty? acc) (compress-typ (rest lst) (list (first lst))))
+; ((not (eq? (first lst) (last acc))) (compress-typ (rest lst) (append acc (first lst))))
+; (#true (compress-typ (rest lst) acc))))
+
+; non-empty lists, non-empty accumulator
+(func compress-typ (lst :{:any} acc :{:any})
+ (if (eq? (first lst) (last acc))
+ (compress-typ (rest lst) acc) ; don't append
+ (compress-typ (rest lst) (append acc (first lst)))))
+
+; non-empty lists, empty accumulator
+(func compress-typ (lst :{:any} acc :nil)
+ (compress-typ (rest lst) (list (first lst))))
+
+;(func extend (lst1 lst2)
+; (reduce append lst2 lst1))
+
+; everything is an expression, so you could do this too
+; not sure if you'd want to, though, as you're creating
+; a list and then immediately killing it, which seems
+; like it's probably wasteful in the interpreter
+;(func compress-typ (lst :{:any} acc :{:any})
+; (compress-typ (rest lst)
+; (extend
+; acc
+; (if (not (eq? (first lst) (last acc)))
+; (list (first lst))))))
+
+
+(print (->string a))
+(print (->string (compress-iter a)))
+(print (->string (compress-typ a)))
diff --git a/p99/p09.neb b/p99/p09.neb
new file mode 100644
index 0000000..619c4a4
--- /dev/null
+++ b/p99/p09.neb
@@ -0,0 +1,31 @@
+; P09 Pack consecutive duplicates of list elements into sublists.
+; If a list contains repeated elements they should be placed in separate sublists.
+
+(def a (list "a" "a" "a" "a" "b" "c" "c" "a" "a" "d" "e" "e" "e" "e"))
+
+; the list, the most recent value, the accumulator
+(func pack-dup (lst)
+ (pack-dup lst "" (list)))
+
+(func pack-dup (lst prev acc)
+ (branch
+ ((empty? lst) acc) ; if we're done, return acc
+ ((eq? (first lst) prev) ; the item is the same as the previous item
+ (pack-dup
+ (rest lst)
+ prev
+ (append ; add item to the last list in acc
+ (most acc)
+ (append
+ (last acc)
+ prev))))
+ (#true
+ (pack-dup
+ (rest lst)
+ (first lst)
+ (append
+ acc
+ (list (first lst))))))) ; add new list with this item
+
+(print (->string a))
+(print (->string (pack-dup a)))
diff --git a/p99/p10.neb b/p99/p10.neb
new file mode 100644
index 0000000..25ea1dc
--- /dev/null
+++ b/p99/p10.neb
@@ -0,0 +1,15 @@
+; P10 Run-length encoding of a list.
+; Use the result of problem P09 to implement the so-called run-length
+; encoding data compression method. Consecutive duplicates of elements
+; are encoded as arrays [N, E] where N is the number of duplicates of the
+; element E.
+
+(use "p09.neb") ; NOTE: this runs everything at this juncture, not just def/func
+
+(func encode (lst)
+ (map
+ (lambda (item)
+ (list (length item) (first item)))
+ lst))
+
+(print (->string (encode (pack-dup a))))
diff --git a/p99/p11.neb b/p99/p11.neb
new file mode 100644
index 0000000..546a7c2
--- /dev/null
+++ b/p99/p11.neb
@@ -0,0 +1,25 @@
+; P11 (*) Modified run-length encoding.
+; Modify the result of problem P10 in such a way that if an element has
+; no duplicates it is simply copied into the result list. Only elements
+; with duplicates are transferred as (N E) lists.
+
+(use "p10.neb")
+
+(func encode-modified (lst)
+ (map
+ (lambda (item)
+ (if (eq? 1 (length item))
+ (first item)
+ (list (length item) (first item))))
+ lst))
+
+(func encode-squish (lst)
+ (map
+ (lambda (item)
+ (if (eq? 1 (first item))
+ (last item)
+ item))
+ lst))
+
+(print (concat "from result of P09: " (->string (encode-modified (pack-dup a)))))
+(print (concat "from result of P10: " (->string (encode-squish (encode (pack-dup a))))))
diff --git a/p99/p12.neb b/p99/p12.neb
new file mode 100644
index 0000000..7d8ec4e
--- /dev/null
+++ b/p99/p12.neb
@@ -0,0 +1,37 @@
+; P12 Decode a run-length encoded list.
+; Given a run-length code list generated as specified in problem P11.
+; Construct its uncompressed version.
+
+(def a (list (list 4 "a") "b" (list 2 "c") (list 2 "a") "d" (list 4 "e")))
+
+(func extend (lst1 lst2)
+ (reduce append lst2 lst1))
+
+(func flatten (lst)
+ (reduce
+ (lambda (x y) (extend x y))
+ lst
+ (list)))
+
+(func decode (lst)
+ (flatten
+ (map
+ (lambda (item)
+ (if (eq? 1 (length item))
+ (list item)
+ (rpt (first item) (last item))))
+ lst)))
+
+(func rpt (cnt let)
+ (if (eq? cnt 1)
+ (list let)
+ (extend (list let) (rpt (- cnt 1) let))))
+
+; iterative
+(func rpt-iter (cnt let)
+ (def out (list))
+ (for-count cnt
+ (redef out (append out let)))
+ out)
+
+(print (->string (decode a)))
diff --git a/p99/p13.neb b/p99/p13.neb
new file mode 100644
index 0000000..e32d8cb
--- /dev/null
+++ b/p99/p13.neb
@@ -0,0 +1,30 @@
+; P13 Run-length encoding of a list (direct solution).
+; Implement the so-called run-length encoding data compression method directly.
+; I.e. don't explicitly create the sublists containing the duplicates, as in problem P09,
+; but only count them. As in problem P11, simplify the result list by replacing the
+; singleton lists (1 X) by X.
+
+(def a (list "a" "a" "a" "a" "b" "c" "c" "a" "a" "d" "e" "e" "e" "e"))
+
+(func encode-direct (lst)
+ (encode-direct lst "" (list)))
+
+(func encode-direct (lst :nil prev acc)
+ acc)
+
+(func encode-direct (lst :{:any} prev acc)
+ (if (eq? (first lst) prev)
+ (encode-direct
+ (rest lst)
+ prev
+ (append (most acc)
+ (if (list? (last acc))
+ (list (+ 1 (first (last acc))) prev)
+ (list 2 prev))))
+ (encode-direct
+ (rest lst)
+ (first lst)
+ (append acc (first lst)))))
+
+(print (->string a))
+(print (->string (encode-direct a)))
diff --git a/p99/p14.neb b/p99/p14.neb
new file mode 100644
index 0000000..5af9fc0
--- /dev/null
+++ b/p99/p14.neb
@@ -0,0 +1,15 @@
+; P14: Duplicate the elements of a list.
+
+(def a (list "a" "b" "c" "c" "d"))
+
+(func dup (lst)
+ (reduce
+ (lambda (acc item)
+ (append
+ (append acc item)
+ item))
+ lst
+ (list)))
+
+(print (->string a))
+(print (->string (dup a)))
diff --git a/p99/p15.neb b/p99/p15.neb
new file mode 100644
index 0000000..12fa8cb
--- /dev/null
+++ b/p99/p15.neb
@@ -0,0 +1,17 @@
+; P15 Replicate the elements of a list a given number of times.
+
+(def a (list "a" "b" "c"))
+
+(func repli (lst cnt)
+ (reduce
+ (lambda (acc item)
+ (def out acc)
+ (for-count cnt
+ (redef out
+ (append out item)))
+ out)
+ lst
+ (list)))
+
+(print (->string a))
+(print (->string (repli a 3)))
diff --git a/p99/p16.neb b/p99/p16.neb
new file mode 100644
index 0000000..e8fc459
--- /dev/null
+++ b/p99/p16.neb
@@ -0,0 +1,19 @@
+; P16 Drop every N'th element from a list.
+
+(def a (list "a" "b" "c" "d" "e" "f" "g" "h" "i" "k"))
+
+(func drop-n (lst n)
+ (drop-n lst n (list) n))
+
+(func drop-n (lst :nil n acc idx)
+ acc)
+
+(func drop-n (lst :{:any} n acc idx)
+ (if (eq? 1 idx)
+ (drop-n (rest lst) n acc n) ; reset n, don't add to acc
+ (drop-n (rest lst) n (append acc (first lst)) (-- idx))))
+
+(func -- (num) (- num 1))
+
+(print (->string a))
+(print (->string (drop-n a 3)))
diff --git a/p99/p17.neb b/p99/p17.neb
new file mode 100644
index 0000000..d586e87
--- /dev/null
+++ b/p99/p17.neb
@@ -0,0 +1,17 @@
+; P17 Split a list into two parts; the length of the first part is given.
+; Do not use any predefined functions.
+
+(def a (list "a" "b" "c" "d" "e" "f" "g" "h" "i" "k"))
+
+(func spl (lst idx)
+ (spl lst idx (list)))
+
+(func spl (lst idx acc)
+ (if (eq? idx 0)
+ (list acc lst)
+ (spl (rest lst) (-- idx) (append acc (first lst)))))
+
+(func -- (num) (- num 1))
+
+(print (->string a))
+(print (->string (spl a 3)))
diff --git a/p99/p18.neb b/p99/p18.neb
new file mode 100644
index 0000000..7ccf0b7
--- /dev/null
+++ b/p99/p18.neb
@@ -0,0 +1,27 @@
+; P18 Extract a slice from a list.
+; Given two indices, I and K, the slice is the list containing the elements between the
+; I'th and K'th element of the original list (both limits included). Start counting the elements with 1.
+
+(def a (list "a" "b" "c" "d" "e" "f" "g" "h" "i" "k"))
+
+(func my-slice (lst idx1 idx2)
+ (my-slice lst idx1 idx2 (list)))
+
+(func my-slice (lst :nil idx1 idx2 acc) acc)
+
+(func my-slice (lst :{:any} idx1 idx2 acc)
+ (my-slice
+ (rest lst)
+ (-- idx1)
+ (-- idx2)
+ (if
+ (or
+ (> idx1 1)
+ (< idx2 1))
+ acc
+ (append acc (first lst)))))
+
+(func -- (num) (- num 1))
+
+(print (->string a))
+(print (->string (my-slice a 3 7)))
diff --git a/p99/p19.neb b/p99/p19.neb
new file mode 100644
index 0000000..09ff324
--- /dev/null
+++ b/p99/p19.neb
@@ -0,0 +1,15 @@
+; P19 Rotate a list N places to the left.
+
+(def a (list "a" "b" "c" "d" "e" "f" "g" "h"))
+
+(func rotate (lst cnt)
+ (branch
+ ((eq? 0 cnt) lst)
+ ((> cnt 0)
+ (rotate (append (rest lst) (first lst)) (- cnt 1)))
+ ((< cnt 0)
+ (rotate (prepend (most lst) (last lst)) (+ cnt 1)))))
+
+(print (->string a))
+(print (->string (rotate a 3)))
+(print (->string (rotate a (- 2))))
diff --git a/p99/p20.neb b/p99/p20.neb
new file mode 100644
index 0000000..06b5e60
--- /dev/null
+++ b/p99/p20.neb
@@ -0,0 +1,21 @@
+; P20 Remove the K'th element from a list.
+
+(def a (list "a" "b" "c" "d"))
+
+(func enumerate (lst)
+ (def ret (list))
+ (for-each lst
+ (redef ret (append ret (list (+ 1 (length ret)) _item_))))
+ ret)
+
+(func extend (lst1 lst2)
+ (reduce append lst2 lst1))
+
+; using slices
+(func remove-at-slice (lst idx)
+ (extend
+ (slice lst 1 (- idx 1))
+ (slice lst (+ idx 1))))
+
+(print (->string a))
+(print (->string (remove-at-slice a 2)))
diff --git a/p99/p21.neb b/p99/p21.neb
new file mode 100644
index 0000000..8b465e9
--- /dev/null
+++ b/p99/p21.neb
@@ -0,0 +1,16 @@
+; P21 Insert an element at a given position into a list
+
+(def a (list "a" "b" "c" "d"))
+
+(func extend (lst1 lst2)
+ (reduce append lst2 lst1))
+
+(func insert-at (item lst idx)
+ (extend
+ (slice lst 1 (- idx 1))
+ (prepend (slice lst idx) item)))
+ ;(slice lst idx)
+ ;(append (slice lst 1 (- idx 1)) item)))
+
+(print (->string a))
+(print (->string (insert-at "f" a 2)))
diff --git a/rosetta/factors-of-int.neb b/rosetta/factors-of-int.neb
new file mode 100644
index 0000000..54115bd
--- /dev/null
+++ b/rosetta/factors-of-int.neb
@@ -0,0 +1,41 @@
+(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)
+
+(func factors (num)
+ (filter
+ (lambda (x)
+ (int? (/ num x)))
+ (.list-of-num (.rough-sqrt num))))
+
+(func factor-pairs (num)
+ (map
+ (lambda (x)
+ (list x (/ num x)))
+ (factors num)))
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))