I've been toying around with random programming languages for about 15 years. I'm just more of a sysadmin type than a programmer, but I've always wanted to do programming, so here I am. I know a bit of C and Python from MIT OCW CS50 (which I didn't complete), and quite a lot of sh/bash. This is all to say I have a very C-like mindset when it comes to programming.
I started using Emacs a few years ago, and Lisp has really grown on me (I'm still firmly in script-kiddie territory in Elisp though). So I decided to try my hand at Common Lisp. I don't do well with courses, video series, or books, so I'm doing hands-on stuff starting with Advent of Code.
I would like it if you all could just point out ways in which I'm not quite "thinking in Lisp terms". Like in the example below, I'm almost certain there's a more "lispy" way to determine whether to add or subtract the first element of INPUT, I just don't know what it is yet. Perhaps something with mapcar?
Without further ado, here is my solution to Advent of Code 2015 Day 1 Part 1 (along with the text of the problem itself):
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.
To what floor do the instructions take Santa?
I was given an input of 7000 characters, so I'll skip that part here. It was something like (()()(()()((()()()))()()))()()((()(((()))((...
;;;; 2015.01.first-attempt.lisp
;;;; Advent of Code 2015 Day 1, first attempt in Lisp
#|| This is really the first "real" bit of code I've written in Common Lisp.
|| Until now I've only ever developed in languages like C, Python, and Bash.
|| I think this is a rather good first attempt with the recursion.
||#
;; ---------------------------------------------------------------------
;;; Package Definition
;; ---------------------------------------------------------------------
(defpackage :2015-01-first-attempt
(:use #:common-lisp))
(in-package :2015-01-first-attempt)
;; ---------------------------------------------------------------------
;;; Definitions
;; ---------------------------------------------------------------------
(defparameter *PUZZLE-INPUT-FILE* "~/proj/Learn/aoc/src/2015.01._PUZZLE-INPUT.txt"
"File to be used as input to the program.")
(defparameter *PUZZLE-INPUT-STRING* (uiop:read-file-string *PUZZLE-INPUT-FILE*)
"String version of the text in `*PUZZLE-INPUT-FILE*'.")
(defparameter *PUZZLE-INPUT* (loop for char across *PUZZLE-INPUT-STRING*
collect char)
"Puzzle input in lisp list form.")
;; ---------------------------------------------------------------------
;;; Part 1
;; -------
;; I think I'm detecting some "code smells" here due to the differences
;; between Lisp and C-likes, but I'm too new at this to tell what it is.
;; If I were to guess, it would be the `cond' in `parse-input'. I think
;; perhaps a better solution would be to `mapcar' the characters with
;; the floor direction in a cons. Again, too new here to know. Might
;; try a second attempt and do that instead.
;; ---------------------------------------------------------------------
(defun parse-input (INPUT)
"Parse `INPUT' to determine where the instructions take Santa."
(let ((FLOOR-NUMBER 0))
(+ FLOOR-NUMBER (cond ((eql (first INPUT) nil) 0)
((eql (first INPUT) #\() (+ 1 (parse-input (rest INPUT))))
((eql (first INPUT) #\)) (- (parse-input (rest INPUT)) 1))))))
;; Test for correct answer (correct answer REDACTED for StackExchange)
(assert (= REDACTED (parse-input *PUZZLE-INPUT*)))
:-)\$\endgroup\$FLOOR-NUMBERdoing there? My level of Lisp understanding is likely lower than yours so I won't attempt answering, but seems like this variable is just set to 0 and added to the final output. Can it just go away? \$\endgroup\$