It's been too long since I wrote any Lisp, so obviously I should use the one hallowed by decades of tradition, not any of the fancy new ones with sane naming conventions and unified library systems. :D
(ql:quickload :str)
(defun parse-insn (insn)
(let ((direction (str:s-first insn))
(magnitude (parse-integer (str:s-rest insn))))
(* magnitude (cond ((equal direction "L") -1)
((equal direction "R") 1)
(t 0)))))
(defun read-inputs-1 (filename)
(let ((input-lines (uiop:read-file-lines filename)))
(destructuring-bind (names _ instructions) input-lines
(list (str:split "," names)
(mapcar #'parse-insn (str:split "," instructions))))))
(defun apply-insns-1 (names insns)
(let ((max-pos (- (length names) 1)))
(labels ((apply-from (insns pos)
(if (null insns)
(nth pos names)
(let* ((maybe-next-pos (+ pos (car insns)))
(next-pos (max 0 (min max-pos maybe-next-pos))))
(apply-from (cdr insns) next-pos)))))
(apply-from insns 0))))
(defun main-1 (filename)
(apply #'apply-insns-1 (read-inputs-1 filename)))
(defun apply-insns-2 (names insns)
(labels ((apply-from (insns pos)
(if (null insns)
(nth pos names)
(let ((next-pos (mod (+ pos (car insns)) (length names))))
(apply-from (cdr insns) next-pos)))))
(apply-from insns 0)))
(defun main-2 (filename)
(apply #'apply-insns-2 (read-inputs-1 filename)))
(defun apply-insns-3 (names insns)
(let* ((vnames (coerce names 'vector))
(n (length vnames)))
(labels ((apply-from (insns)
(if (null insns)
(aref vnames 0)
(let* ((tgt (mod (car insns) n))
(src-name (aref vnames 0))
(tgt-name (aref vnames tgt)))
(setf (aref vnames 0) tgt-name)
(setf (aref vnames tgt) src-name)
(apply-from (cdr insns))))))
(apply-from insns))))
(defun main-3 (filename)
(apply #'apply-insns-3 (read-inputs-1 filename)))