summaryrefslogtreecommitdiff
path: root/2015/day12.exs
blob: df77e945e9ee2f9db2894b8c8e665fff0c555722 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
jsonString = String.trim(File.read!("inputs/day12.txt"))

numberSum =
  Regex.scan(~r/[+-]?\d+/, jsonString)
  |> Enum.map(fn [numString] ->
    {num, ""} = Integer.parse(numString)
    num
  end)
  |> Enum.sum()

IO.puts("Number sum: #{numberSum}")

defmodule JsonParser do
  def sumNonRedNumbers(<<"{" <> rest>>) do
    [{:end, redStatus, sum, rest}] =
      Stream.iterate({:open, :not_red, 0, rest}, fn {_, redStatus, sum, rest} ->
        {endNow, newRedStaus, subSum, rest} = readObjectContent(rest)

        {endNow,
         if newRedStaus == :red do
           :red
         else
           redStatus
         end, sum + subSum, rest}
      end)
      |> Stream.filter(fn
        {:end, _, _, _} -> true
        _ -> false
      end)
      |> Enum.take(1)

    sum =
      if redStatus == :red do
        0
      else
        sum
      end

    {sum, rest}
  end

  def sumNonRedNumbers(<<"\"" <> rest>>) do
    [_, rest] = String.split(rest, "\"", parts: 2)
    {0, rest}
  end

  def sumNonRedNumbers(<<"[" <> rest>>) do
    [{:end, sum, rest}] =
      Stream.iterate({:open, 0, rest}, fn {_, sum, rest} ->
        {endNow, subSum, rest} = readArrayContent(rest)
        {endNow, sum + subSum, rest}
      end)
      |> Stream.filter(fn
        {:end, _, _} -> true
        _ -> false
      end)
      |> Enum.take(1)

    {sum, rest}
  end

  def sumNonRedNumbers(numberNext) do
    Integer.parse(numberNext)
  end

  def readObjectContent(<<"\"" <> rest>>) do
    [_, rest] = String.split(rest, "\":", parts: 2)

    case rest do
      <<"\"red\"" <> rest>> ->
        {:open, :red, 0, rest}

      _ ->
        {sum, rest} = sumNonRedNumbers(rest)
        {:open, :not_red, sum, rest}
    end
  end

  def readObjectContent(<<"," <> rest>>) do
    {:open, :not_red, 0, rest}
  end

  def readObjectContent(<<"}" <> rest>>) do
    {:end, :not_red, 0, rest}
  end

  def readArrayContent(<<"," <> rest>>) do
    {:open, 0, rest}
  end

  def readArrayContent(<<"]" <> rest>>) do
    {:end, 0, rest}
  end

  def readArrayContent(json) do
    {sum, rest} = sumNonRedNumbers(json)
    {:open, sum, rest}
  end
end

{nonRedNumbers, ""} = JsonParser.sumNonRedNumbers(jsonString)

IO.puts("Non red number sum: #{nonRedNumbers}")