Advent of Code 2015 - Day 1 - Not Quite Lisp

{:deps
 {org.clojure/clojure {:mvn/version "1.10.1-RC1"}}}
deps.edn
Extensible Data Notation

Santa is trying to deliver presents in a large apartment building, but he can't find the right floor – the directions he got are a little confusing. He starts on the ground floor (floor 0) and then follows the instructions one character at a time.

An opening parenthesis, (, means he should go up one floor, and a closing parenthesis, ), means he should go down one floor.

The apartment building is very tall, and the basement is very deep; he will never find the top or bottom floors.

For example:

  • (()) and ()() both result in floor 0.
  • ((( and (()(()( both result in floor 3.
  • ))((((( also results in floor 3.
  • ()) and ))( both result in floor -1 (the first basement level).
  • ))) and )())()) both result in floor -3.
input

1. Part One

To what floor do the instructions take Santa?

1.1. Bash

echo 'c=0; n=1
for i in $(fold -b1 $1); do
    [ "$i" = "(" ] && c=$((c+1))
    [ "$i" = ")" ] && c=$((c-1))
    echo $c $n
    n=$((n+1))
done' > day1.sh
sh day1.sh input | tail -n1 | cut -d' ' -f1

1.2. AWK

awk 'BEGIN {
	FS = "";
}
{
	for (i = 1; i <= NF; i++) {
		if ($i == "(")
			floor++;
		else if ($i == ")")
			floor--;
	}
}
END {
	print floor;
}' input

1.3. Clojure

(- (count (re-seq #"\(" (slurp "input")))
   (count (re-seq #"\)" (slurp "input"))))
-699
(defn parse-step [floor step]
  (case step
    \( (inc floor)
    \) (dec floor)
    floor))

(defn parse-floor
  [steps]
  (reduce parse-step 0 steps))

(parse-floor (slurp "input"))
-699

2. Part Two

Now, given the same instructions, find the position of the first character that causes him to enter the basement (floor -1). The first character in the instructions has position 1, the second character has position 2, and so on.

For example:

  • ) causes him to enter the basement at character position 1.
  • ()()) causes him to enter the basement at character position 5.What is the position of the character that causes Santa to first enter the basement?

2.1. Bash

sh day1.sh input | grep -e '-1 ' | head -n1 | cut -d' ' -f2

2.2. AWK

awk 'BEGIN {
	# split the input into one field per character.
	FS = "";
	THE_BASEMENT = -1;
}

{
	for (i = 1; i <= NF; i++) {
		if ($i == "(")
			floor++;
		else if ($i == ")")
			floor--;
		if (floor == THE_BASEMENT)
			break;
	}
}

END {
	# i is the position, if santa never entered the basement then we have:
	# i == (NR + 1)
	print i;
}' input

2.3. Clojure

(defn basement
  [instructions]
  (->> instructions
       (reductions parse-step 0)
       (map vector (drop 1 (range)))
       (drop-while (fn [[position floor]] (not (neg? floor))))
       first
       first))

(dec (basement (slurp "input")))
1795