Post: Advent of Code 2017 day 1

This commit is contained in:
Jez Cope 2017-12-01 20:52:02 +00:00
parent 1c701c5593
commit 76d733b6fd
4 changed files with 126 additions and 23 deletions

View File

@ -13,3 +13,4 @@ nikola = "*"
"jinja2" = "*"
notebook = "*"
"s3cmd" = "*"
coconut = "*"

63
Pipfile.lock generated
View File

@ -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": [

View File

@ -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',
}

View File

@ -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
```