diff options
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)) |
