Advent of Code 2018


#1

https://adventofcode.com/2018

Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.


#2

我的 Emacs Lisp 解答:


#3

挺好玩,贴一个 day 1 的 Clojure 解答。有空再跟进整理

;; language: clojure
;;;; helpers
(defn to-i [s] (Integer/parseInt s))
(def my-input-list (map to-i (line-seq (clojure.java.io/reader "input.txt"))))

;;;; day one
;; part 1
(apply + my-input-list)

;; part 2
(defn f [sets sum list]
  (let [head (first list),
        tail (rest list),
        now-sum (+ head sum),
        now-sets (conj sets now-sum)]
    (cond
      (sets now-sum) now-sum
      (empty? tail) (recur now-sets now-sum my-input-list)
      true (recur now-sets now-sum tail))))

(f #{} 0 my-input-list)
;; 楼主花了将近 50 秒,我这就用了 1 秒。。。是都花在花哨的交互上了么 XD

Day2

# language: elixir
# Unit
input =
  File.open!("input.txt")
  |> IO.read(:all)
  |> String.split()

# Day Two Part One
input
|> Enum.reduce({0, 0}, fn(str, {s, t}) ->
  freqs =
    String.graphemes(str)
    |> Enum.group_by(&(&1))
    |> Enum.map(fn({_, v}) -> length(v) end)

  fun = &(if Enum.member?(freqs, &1), do: 1, else: 0)

  {s + fun.(2), t + fun.(3)}
end)
|> (fn({s, t}) -> s * t end).()

# Day Two Part Two
input
|> Enum.find_value(fn(now_str) ->
  Enum.find_value(input, fn(s) ->
    diff = String.myers_difference(now_str, s)
    if 4 == length(diff) do
      del = Keyword.get(diff, :del) || ""
      ins = Keyword.get(diff, :ins) || ""

      if String.length(del) == 1 && String.length(ins) == 1, do: diff
    end
  end)
end)
|> Keyword.take([:eq])
|> (fn([{_, x}, {_, y}]) -> x <> y end).()

#4

不清楚为什么很慢,我的代码并没有什么「交互」。此外要注意每个人的输入都不同。


#5

用 SNOBOL4 写的。

         &anchor  = 1
         digits   = '0123456789'
         freq     = 0
         pat      = (any('+-') . sign) (span(digits) . val)
loop     input pat                   :f(fin)
         sign '+'                    :s(add)f(min)
add      freq     = freq + val       :(loop)
min      freq     = freq - val       :(loop)
fin      output   = freq
end
>> 0:~ $ time cat Downloads/input.txt  | spitbol day1.snb                                 << 19:57 <]
        0.00 real         0.00 user         0.00 sys

Part 2 要用到 IO,稍有一點麻煩。

         &anchor  = 1
         digits   = '0123456789'
         freq     = 0
         sat      = table(1000,500)
         sat<0>   = 1
         pat      = (any('+-') . sign) (span(digits) . val)
open     input('data',1)
loop     data pat                    :f(endf)
         sign '+'                    :s(add)f(min)
endf     endfile(1)                  :(open)
add      freq     = freq + val       :(hash)
min      freq     = freq - val
hash     sat<freq>  = sat<freq> + 1
         eq(sat<freq>, 2)            :f(loop)
fin      output   = freq
end
>> 0:~ $ time spitbol -1=input.txt day1-2.snb                                             << 20:45 <]
        0.39 real         0.38 user         0.00 sys
>> 0:~ $ wc -l input.txt                                                                  << 21:00 <]
    1025 input.txt

Day2 part1

>> 0:~ $ cat day2.snb                                                                     << 23:38 <]
        &anchor = 1
        three   = 0
        two     = 0
        pat     = len(1) . char
loop    line = input            :f(fin)
        stat = table(30)
in      line pat =              :f(set)
        gt(stat<char>, 3)       :s(in)
        eq(stat<char>, 3)       :f(nt)
        accu3 = accu3 - 1       :(inc)
nt      eq(stat<char>, 2)       :f(nxt)
        accu2 = accu2 - 1
        accu3 = accu3 + 1       :(inc)
nxt     eq(stat<char>, 1)       :f(inc)
        accu2 = accu2 + 1
inc     stat<char> = stat<char> + 1 :(in)
set     gt(accu3, 0)            :f(nn)
        three = three + 1
nn      gt(accu2, 0)            :f(cl)
        two = two + 1
cl      accu3   = 0
        accu2   = 0             :(loop)
fin     res = two * three
        output = 'res:' two '*' three '=' res
end
>> 0:~ $ time cat input.txt | spitbol day2.snb                                            << 23:38 <]
        0.00 real         0.00 user         0.00 sys
res:249*23=5727

#6

1-1

%{
#include <math.h>
long sum = 0;
%}

%%

[+-]?[0-9]+   { sum += atoi( yytext ) ;}
[ \t\n]+     /* eat up whitespace */
.           printf( "Unrecognized character: %s\n", yytext );

%%

int main( int argc, char **argv ){

    ++argv, --argc;  /* skip over program name */

    if ( argc > 0 )
        yyin = fopen( argv[0], "r" );
    else
        yyin = stdin;
    yylex();
    printf("the sum:%ld",sum);
}

#7

我觉得1-2应该增加点难度

找出发生重复所在的行