Post: Advent of Code 2017 day 1
This commit is contained in:
parent
1c701c5593
commit
76d733b6fd
1
Pipfile
1
Pipfile
|
@ -13,3 +13,4 @@ nikola = "*"
|
|||
"jinja2" = "*"
|
||||
notebook = "*"
|
||||
"s3cmd" = "*"
|
||||
coconut = "*"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "42ac71177d1abf96d8fd30631dfef13f03e86a3e85a2393aceb8215710180b5d"
|
||||
"sha256": "78190ec3192561703386492a41df6fbed72e5741b6a7e7d5b269f03e279045bb"
|
||||
},
|
||||
"host-environment-markers": {
|
||||
"implementation_name": "cpython",
|
||||
|
@ -9,9 +9,9 @@
|
|||
"os_name": "posix",
|
||||
"platform_machine": "x86_64",
|
||||
"platform_python_implementation": "CPython",
|
||||
"platform_release": "4.13.10-1-ARCH",
|
||||
"platform_release": "4.13.12-1-ARCH",
|
||||
"platform_system": "Linux",
|
||||
"platform_version": "#1 SMP PREEMPT Fri Oct 27 16:16:03 CEST 2017",
|
||||
"platform_version": "#1 SMP PREEMPT Wed Nov 8 11:54:06 CET 2017",
|
||||
"python_full_version": "3.6.3",
|
||||
"python_version": "3.6",
|
||||
"sys_platform": "linux"
|
||||
|
@ -62,10 +62,17 @@
|
|||
},
|
||||
"cloudpickle": {
|
||||
"hashes": [
|
||||
"sha256:a34d5e83b20b9cebf759bd5d244ec4bac3442971d2d5eb0941cd4ca2be33eaa2",
|
||||
"sha256:a03a155c1fceacd817d3c84eed710fbe8ccf3ca9a553283c4666edf989eaffaa"
|
||||
"sha256:604c1cb39c2043ba44f017444dd89b7f82541701dfa8a64f5ae72e6346755c0b",
|
||||
"sha256:b0e63dd89ed5285171a570186751bc9b84493675e99e12789e9a5dc5490ef554"
|
||||
],
|
||||
"version": "==0.4.1"
|
||||
"version": "==0.5.2"
|
||||
},
|
||||
"coconut": {
|
||||
"hashes": [
|
||||
"sha256:6660212af3fbc0890b1d94b18d49c9718325e4af0661cc3ad7c69902f62cc7b0",
|
||||
"sha256:311e5cbf8179a234a53abe748b4e2fa7c2d7ae658661075741d02f2cc21ba832"
|
||||
],
|
||||
"version": "==1.3.1"
|
||||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
|
@ -141,10 +148,10 @@
|
|||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054",
|
||||
"sha256:ddaa01a212cd6d641401cb01b605f4a4d9f37bfc93043d7f760ec70fb99ff9ff"
|
||||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
|
||||
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
|
||||
],
|
||||
"version": "==2.9.6"
|
||||
"version": "==2.10"
|
||||
},
|
||||
"jsonschema": {
|
||||
"hashes": [
|
||||
|
@ -243,10 +250,10 @@
|
|||
},
|
||||
"natsort": {
|
||||
"hashes": [
|
||||
"sha256:64b702ee943144beea9cc58f4b2893da3bc3dfa9bd31cd216f8bfd6dce6edf57",
|
||||
"sha256:5db0fd17c9f8ef3d54962a6e46159ce4807c630f0931169cd15ce54f2ac395b9"
|
||||
"sha256:ee2f7715bf45a65cc1ab1d80360b00299102c7bf9d87757a27e14ddaafa57d0e",
|
||||
"sha256:9ffbfb74bf3fc3905be1b9b052ed865675651e38fcd972ed1ed5c64a02f93cbd"
|
||||
],
|
||||
"version": "==5.1.0"
|
||||
"version": "==5.1.1"
|
||||
},
|
||||
"nbconvert": {
|
||||
"hashes": [
|
||||
|
@ -271,10 +278,10 @@
|
|||
},
|
||||
"notebook": {
|
||||
"hashes": [
|
||||
"sha256:7ed09a3007ad6f39e112598edad951c35c85799d928bea831f3ecd5c95100688",
|
||||
"sha256:4ae5b81dd39b37cdd99dcffe83a5182c849947b92d46ac4d2b5093af2bb9f224"
|
||||
"sha256:8d63d3370800e41888e186af68a49ba7cfa1b2155a5de7fc167969c458872587",
|
||||
"sha256:7bb54fb61b9c5426bc116f840541b973431198e00ea2896122d05fc122dbbd67"
|
||||
],
|
||||
"version": "==5.2.1"
|
||||
"version": "==5.2.2"
|
||||
},
|
||||
"olefile": {
|
||||
"hashes": [
|
||||
|
@ -303,11 +310,11 @@
|
|||
},
|
||||
"pexpect": {
|
||||
"hashes": [
|
||||
"sha256:f853b52afaf3b064d29854771e2db509ef80392509bde2dd7a6ecf2dfc3f0018",
|
||||
"sha256:3d132465a75b57aa818341c6521392a06cc660feb3988d7f1074f39bd23c9a92"
|
||||
"sha256:2b50dd8caa5007b10b0afcf075095814780b104b4a5cf9d8fbdc8bbc754e5ca4",
|
||||
"sha256:00ab0872f80f5db740499e7a1283a7c3b97bea542d72df84d83dea17d0afd2d9"
|
||||
],
|
||||
"markers": "sys_platform != 'win32'",
|
||||
"version": "==4.2.1"
|
||||
"version": "==4.3.0"
|
||||
},
|
||||
"pickleshare": {
|
||||
"hashes": [
|
||||
|
@ -381,6 +388,7 @@
|
|||
"sha256:1df952620eccb399c53ebb359cc7d9a8d3a9538cb34c5a1344bdbeb29fbcc381",
|
||||
"sha256:858588f1983ca497f1cf4ffde01d978a3ea02b01c8a26a8bbc5cd2e66d816917"
|
||||
],
|
||||
"markers": "python_version >= '2.7'",
|
||||
"version": "==1.0.15"
|
||||
},
|
||||
"ptyprocess": {
|
||||
|
@ -388,6 +396,7 @@
|
|||
"sha256:e8c43b5eee76b2083a9badde89fd1bbce6c8942d1045146e100b7b5e014f4f1a",
|
||||
"sha256:e64193f0047ad603b71f202332ab5527c5e52aa7c8b609704fc28c0dc20c4365"
|
||||
],
|
||||
"markers": "os_name != 'nt'",
|
||||
"version": "==0.5.2"
|
||||
},
|
||||
"pygments": {
|
||||
|
@ -395,6 +404,7 @@
|
|||
"sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d",
|
||||
"sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc"
|
||||
],
|
||||
"markers": "python_version >= '2.7'",
|
||||
"version": "==2.2.0"
|
||||
},
|
||||
"pyinotify": {
|
||||
|
@ -403,6 +413,18 @@
|
|||
],
|
||||
"version": "==0.9.6"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010",
|
||||
"sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04",
|
||||
"sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e",
|
||||
"sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07",
|
||||
"sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5",
|
||||
"sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18",
|
||||
"sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58"
|
||||
],
|
||||
"version": "==2.2.0"
|
||||
},
|
||||
"pyrss2gen": {
|
||||
"hashes": [
|
||||
"sha256:7960aed7e998d2482bf58716c316509786f596426f879b05f8d84e98b82c6ee7"
|
||||
|
@ -505,10 +527,11 @@
|
|||
},
|
||||
"terminado": {
|
||||
"hashes": [
|
||||
"sha256:2c0ba1f624067dccaaead7d2247cfe029806355cef124dc2ccb53c83229f0126"
|
||||
"sha256:65011551baff97f5414c67018e908110693143cfbaeb16831b743fe7cad8b927",
|
||||
"sha256:55abf9ade563b8f9be1f34e4233c7b7bde726059947a593322e8a553cc4c067a"
|
||||
],
|
||||
"markers": "sys_platform != 'win32'",
|
||||
"version": "==0.6"
|
||||
"version": "==0.8.1"
|
||||
},
|
||||
"testpath": {
|
||||
"hashes": [
|
||||
|
|
5
conf.py
5
conf.py
|
@ -260,9 +260,7 @@ FILES_FOLDERS = {
|
|||
|
||||
# One or more folders containing code listings to be processed and published on
|
||||
# the site. The format is a dictionary of {source: relative destination}.
|
||||
# Default is:
|
||||
# LISTINGS_FOLDERS = {'listings': 'listings'}
|
||||
# Which means process listings from 'listings' into 'output/listings'
|
||||
LISTINGS_FOLDERS = {'code': 'code'}
|
||||
|
||||
# A mapping of languages to file-extensions that represent that language.
|
||||
# Feel free to add or delete extensions to any list, but don't add any new
|
||||
|
@ -1345,4 +1343,5 @@ SASS_OPTIONS = []
|
|||
SERIES_DESCRIPTIONS = {
|
||||
'swc-archaeology': 'the origins of [Software Carpentry](http://software-carpentry.org)',
|
||||
'lean-libraries': 'applying lean principles in library & information work',
|
||||
'aoc2017': 'my attempts to complete the [Advent of Code 2017](http://adventofcode.com) challenges',
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
title: "Inverse Captcha — Coconut — #adventofcode Day 1"
|
||||
description: "In which I try to prove I am not human."
|
||||
slug: day-01
|
||||
date: 2017-12-01T14:35:40+00:00
|
||||
tags:
|
||||
- Technology
|
||||
- Learning
|
||||
- Advent of Code
|
||||
- Python
|
||||
- Coconut
|
||||
series: aoc2017
|
||||
---
|
||||
|
||||
Well, December's here at last, and with it [Day 1 of Advent of Code](http://adventofcode.com/2017/day/1).
|
||||
|
||||
> … It goes on to explain that you may only leave by solving a captcha to prove you're not a human. Apparently, you only get one millisecond to solve the captcha: too fast for a normal human, but it feels like hours to you. …
|
||||
|
||||
As well as posting solutions here when I can, I'll be putting them all on <https://github.com/jezcope/aoc2017> too.
|
||||
|
||||
!!! commentary
|
||||
After doing some challenges from last year in [Haskell][] for a warm up, I felt inspired to try out the functional-ish Python dialect, [Coconut][]. Now that I've done it, it feels a bit of an odd language, [neither fish nor fowl][]. It'll look familiar to any Pythonista, but is loaded with features normally associated with functional languages, like pattern matching, destructuring assignment, partial application and function composition.
|
||||
|
||||
That makes it quite fun to work with, as it works similarly to Haskell, but because it's restricted by the basic rules of Python syntax everything feels a bit more like hard work than it should.
|
||||
|
||||
The accumulator approach feels clunky, but it's necessary to allow [tail call elimination](https://en.wikipedia.org/wiki/Tail_call), which Coconut will do and I wanted to see in action. Lo and behold, if you take a look at the [compiled Python version](https://github.com/jezcope/aoc2017/blob/86c8100824bda1b35e5db6e02d4b80890be7a022/01-inverse-captcha.py#L675) you'll see that my recursive implementation has been turned into a non-recursive `while` loop.
|
||||
|
||||
Then again, maybe I'm just jealous of Phil Tooley's [one-liner solution in Python](https://github.com/ptooley/aocGolf/blob/1380d78194f1258748ccfc18880cfd575baf5d37/2017.py#L8).
|
||||
|
||||
[Haskell]: https://www.haskell.org
|
||||
[Coconut]: http://coconut-lang.org
|
||||
[neither fish nor fowl]: https://en.wiktionary.org/wiki/neither_fish_nor_fowl
|
||||
|
||||
```coconut
|
||||
import sys
|
||||
|
||||
def inverse_captcha_(s, acc=0):
|
||||
case reiterable(s):
|
||||
match (|d, d|) :: rest:
|
||||
return inverse_captcha_((|d|) :: rest, acc + int(d))
|
||||
match (|d0, d1|) :: rest:
|
||||
return inverse_captcha_((|d1|) :: rest, acc)
|
||||
|
||||
return acc
|
||||
|
||||
|
||||
def inverse_captcha(s) = inverse_captcha_(s :: s[0])
|
||||
|
||||
|
||||
def inverse_captcha_1_(s0, s1, acc=0):
|
||||
case (reiterable(s0), reiterable(s1)):
|
||||
match ((|d0|) :: rest0, (|d0|) :: rest1):
|
||||
return inverse_captcha_1_(rest0, rest1, acc + int(d0))
|
||||
match ((|d0|) :: rest0, (|d1|) :: rest1):
|
||||
return inverse_captcha_1_(rest0, rest1, acc)
|
||||
|
||||
return acc
|
||||
|
||||
|
||||
def inverse_captcha_1(s) = inverse_captcha_1_(s, s$[len(s)//2:] :: s)
|
||||
|
||||
|
||||
def test_inverse_captcha():
|
||||
assert "1111" |> inverse_captcha == 4
|
||||
assert "1122" |> inverse_captcha == 3
|
||||
assert "1234" |> inverse_captcha == 0
|
||||
assert "91212129" |> inverse_captcha == 9
|
||||
|
||||
|
||||
def test_inverse_captcha_1():
|
||||
assert "1212" |> inverse_captcha_1 == 6
|
||||
assert "1221" |> inverse_captcha_1 == 0
|
||||
assert "123425" |> inverse_captcha_1 == 4
|
||||
assert "123123" |> inverse_captcha_1 == 12
|
||||
assert "12131415" |> inverse_captcha_1 == 4
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.argv[1] |> inverse_captcha |> print
|
||||
sys.argv[1] |> inverse_captcha_1 |> print
|
||||
```
|
Loading…
Reference in New Issue