├── 2015 ├── day-01 │ ├── README.md │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.md │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.md │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.md │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.md │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.md │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.md │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.md │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.md │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.md │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.md │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.md │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.md │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.md │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.md │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.md │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.md │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-18 │ ├── README.md │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-19 │ ├── README.md │ ├── day-19-input.txt │ ├── day-19-part-1.rb │ └── day-19-part-2.rb ├── day-20 │ ├── README.md │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.md │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb ├── day-22 │ ├── README.md │ ├── day-22-input.txt │ ├── day-22-part-1.rb │ └── day-22-part-2.rb ├── day-23 │ ├── README.md │ ├── day-23-input.txt │ ├── day-23-part-1.rb │ └── day-23-part-2.rb ├── day-24 │ ├── README.md │ ├── day-24-input.txt │ ├── day-24-part-1.rb │ └── day-24-part-2.rb └── day-25 │ ├── README.md │ ├── day-25-input.txt │ └── day-25-part-1.rb ├── 2016 ├── day-01 │ ├── README.md │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.md │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.md │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.md │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.md │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.md │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.md │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.md │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.md │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.md │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.md │ ├── day-11-input-part-2.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.md │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.md │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.md │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.md │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.md │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.md │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-18 │ ├── README.md │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-19 │ ├── README.md │ ├── day-19-input.txt │ ├── day-19-part-1.rb │ └── day-19-part-2.rb ├── day-20 │ ├── README.md │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.md │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb ├── day-22 │ ├── README.md │ ├── day-22-input.txt │ ├── day-22-part-1.rb │ └── day-22-part-2.rb ├── day-23 │ ├── README.md │ ├── day-23-input-part-2.txt │ ├── day-23-input.txt │ ├── day-23-part-1.rb │ └── day-23-part-2.rb ├── day-24 │ ├── README.md │ ├── day-24-input.txt │ ├── day-24-part-1.rb │ └── day-24-part-2.rb └── day-25 │ ├── README.md │ ├── day-25-input.txt │ └── day-25-part-1.rb ├── 2017 ├── day-01 │ ├── README.md │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.md │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.md │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.md │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.md │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.md │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.md │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.md │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.md │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.md │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.md │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.md │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.md │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.md │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.md │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.md │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.md │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-18 │ ├── README.md │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-19 │ ├── README.md │ ├── day-19-input.txt │ ├── day-19-part-1.rb │ └── day-19-part-2.rb ├── day-20 │ ├── README.md │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.md │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb ├── day-22 │ ├── README.md │ ├── day-22-input.txt │ ├── day-22-part-1.rb │ └── day-22-part-2.rb ├── day-23 │ ├── README.md │ ├── day-23-input.txt │ ├── day-23-part-1.rb │ └── day-23-part-2.rb ├── day-24 │ ├── README.md │ ├── day-24-input.txt │ ├── day-24-part-1.rb │ └── day-24-part-2.rb └── day-25 │ ├── README.md │ ├── day-25-input.txt │ └── day-25-part-1.rb ├── 2018 ├── day-01 │ ├── README.txt │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.txt │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.txt │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.txt │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.txt │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.txt │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.txt │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.txt │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.txt │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.txt │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.txt │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.txt │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.txt │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.txt │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.txt │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.txt │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-18 │ ├── README.txt │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-19 │ ├── README.txt │ ├── day-19-input.txt │ ├── day-19-part-1.rb │ └── day-19-part-2.rb ├── day-20 │ ├── README.txt │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.txt │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb ├── day-22 │ ├── README.txt │ ├── day-22-input.txt │ ├── day-22-part-1.rb │ └── day-22-part-2.rb ├── day-23 │ ├── README.txt │ ├── day-23-input.txt │ ├── day-23-part-1.rb │ └── day-23-part-2.rb ├── day-24 │ ├── README.txt │ ├── day-24-input.txt │ ├── day-24-part-1.rb │ └── day-24-part-2.rb └── day-25 │ ├── README.txt │ ├── day-25-input.txt │ └── day-25-part-1.rb ├── 2019 ├── day-01 │ ├── README.txt │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.txt │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.txt │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.txt │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.txt │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.txt │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.txt │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.txt │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.txt │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.txt │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.txt │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.txt │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.txt │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.txt │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.txt │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.txt │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-21 │ ├── README.txt │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb └── day-22 │ ├── README.txt │ ├── day-22-input.txt │ └── day-22-part-1.rb ├── 2020 ├── day-01 │ ├── README.txt │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.txt │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.txt │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.txt │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.txt │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.txt │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.txt │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.txt │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.txt │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.txt │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.txt │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.txt │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.txt │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.txt │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.txt │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.txt │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-18 │ ├── README.txt │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-19 │ ├── README.txt │ ├── day-19-input.txt │ ├── day-19-part-1.rb │ └── day-19-part-2.rb ├── day-20 │ ├── README.txt │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.txt │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb ├── day-22 │ ├── README.txt │ ├── day-22-input.txt │ ├── day-22-part-1.rb │ └── day-22-part-2.rb ├── day-23 │ ├── README.txt │ ├── day-23-input.txt │ ├── day-23-part-1.rb │ └── day-23-part-2.rb ├── day-24 │ ├── README.txt │ ├── day-24-input.txt │ ├── day-24-part-1.rb │ └── day-24-part-2.rb └── day-25 │ ├── README.txt │ ├── day-25-input.txt │ └── day-25-part-1.rb ├── 2021 ├── day-01 │ ├── README.txt │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.txt │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.txt │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.txt │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.txt │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.txt │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.txt │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.txt │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.txt │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.txt │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.txt │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.txt │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.txt │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.txt │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.txt │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.txt │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb └── day-18 │ ├── README.txt │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── 2022 ├── day-01 │ ├── README.txt │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.txt │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.txt │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.txt │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.txt │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.txt │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.txt │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.txt │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.txt │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.txt │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.txt │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.txt │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.txt │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.txt │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.txt │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.txt │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-18 │ ├── README.txt │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-20 │ ├── README.txt │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.txt │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb └── day-22 │ ├── README.txt │ ├── day-22-input.txt │ ├── day-22-part-1.rb │ └── day-22-part-2.rb ├── 2023 ├── day-01 │ ├── README.txt │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.txt │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.txt │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.txt │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.txt │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.txt │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.txt │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.txt │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.txt │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.txt │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ ├── day-10-part-2-alt.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.txt │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.txt │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.txt │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.txt │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.txt │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.txt │ ├── day-17-input.txt │ └── day-17-part-1-and-2.rb ├── day-18 │ ├── README.txt │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-19 │ ├── README.txt │ ├── day-19-input.txt │ ├── day-19-part-1.rb │ └── day-19-part-2.rb ├── day-20 │ ├── README.txt │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.txt │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb ├── day-22 │ ├── README.txt │ ├── day-22-input.txt │ └── day-22-part-1-and-2.rb ├── day-23 │ ├── README.txt │ ├── day-23-input.txt │ ├── day-23-part-1.rb │ └── day-23-part-2.rb ├── day-24 │ ├── README.txt │ ├── day-24-input.txt │ ├── day-24-part-1.rb │ └── day-24-part-2.rb └── day-25 │ ├── README.txt │ ├── day-25-input.txt │ └── day-25-part-1.rb ├── 2024 ├── day-01 │ ├── README.txt │ ├── day-01-input.txt │ ├── day-01-part-1.rb │ └── day-01-part-2.rb ├── day-02 │ ├── README.txt │ ├── day-02-input.txt │ ├── day-02-part-1.rb │ └── day-02-part-2.rb ├── day-03 │ ├── README.txt │ ├── day-03-input.txt │ ├── day-03-part-1.rb │ └── day-03-part-2.rb ├── day-04 │ ├── README.txt │ ├── day-04-input.txt │ ├── day-04-part-1.rb │ └── day-04-part-2.rb ├── day-05 │ ├── README.txt │ ├── day-05-input.txt │ ├── day-05-part-1.rb │ └── day-05-part-2.rb ├── day-06 │ ├── README.txt │ ├── day-06-input.txt │ ├── day-06-part-1.rb │ └── day-06-part-2.rb ├── day-07 │ ├── README.txt │ ├── day-07-input.txt │ ├── day-07-part-1.rb │ └── day-07-part-2.rb ├── day-08 │ ├── README.txt │ ├── day-08-input.txt │ ├── day-08-part-1.rb │ └── day-08-part-2.rb ├── day-09 │ ├── README.txt │ ├── day-09-input.txt │ ├── day-09-part-1.rb │ └── day-09-part-2.rb ├── day-10 │ ├── README.txt │ ├── day-10-input.txt │ ├── day-10-part-1.rb │ └── day-10-part-2.rb ├── day-11 │ ├── README.txt │ ├── day-11-input.txt │ ├── day-11-part-1.rb │ └── day-11-part-2.rb ├── day-12 │ ├── README.txt │ ├── day-12-input.txt │ ├── day-12-part-1.rb │ └── day-12-part-2.rb ├── day-13 │ ├── README.txt │ ├── day-13-input.txt │ ├── day-13-part-1.rb │ └── day-13-part-2.rb ├── day-14 │ ├── README.txt │ ├── day-14-input.txt │ ├── day-14-part-1.rb │ └── day-14-part-2.rb ├── day-15 │ ├── README.txt │ ├── day-15-input.txt │ ├── day-15-part-1.rb │ └── day-15-part-2.rb ├── day-16 │ ├── README.txt │ ├── day-16-input.txt │ ├── day-16-part-1.rb │ └── day-16-part-2.rb ├── day-17 │ ├── README.txt │ ├── day-17-input.txt │ ├── day-17-part-1.rb │ └── day-17-part-2.rb ├── day-18 │ ├── README.txt │ ├── day-18-input.txt │ ├── day-18-part-1.rb │ └── day-18-part-2.rb ├── day-19 │ ├── README.txt │ ├── day-19-input.txt │ ├── day-19-part-1.rb │ └── day-19-part-2.rb ├── day-20 │ ├── README.txt │ ├── day-20-input.txt │ ├── day-20-part-1.rb │ └── day-20-part-2.rb ├── day-21 │ ├── README.txt │ ├── day-21-input.txt │ ├── day-21-part-1.rb │ └── day-21-part-2.rb ├── day-22 │ ├── README.txt │ ├── day-22-input.txt │ ├── day-22-part-1.rb │ └── day-22-part-2.rb ├── day-23 │ ├── README.txt │ ├── day-23-input.txt │ ├── day-23-part-1.rb │ └── day-23-part-2.rb ├── day-24 │ ├── README.txt │ ├── day-24-input.txt │ ├── day-24-part-1.rb │ └── day-24-part-2.rb └── day-25 │ ├── README.txt │ ├── day-25-input.txt │ └── day-25-part-1.rb ├── .gitignore ├── .tool-versions ├── LICENSE ├── README.md ├── create_files.sh └── template.rb /.gitignore: -------------------------------------------------------------------------------- 1 | # Source: 2 | # https://github.com/github/gitignore/blob/master/Ruby.gitignore 3 | 4 | # Additions 5 | .DS_Store 6 | 7 | *.gem 8 | *.rbc 9 | /.config 10 | /coverage/ 11 | /InstalledFiles 12 | /pkg/ 13 | /spec/reports/ 14 | /test/tmp/ 15 | /test/version_tmp/ 16 | /tmp/ 17 | 18 | ## Specific to RubyMotion: 19 | .dat* 20 | .repl_history 21 | build/ 22 | 23 | ## Documentation cache and generated files: 24 | /.yardoc/ 25 | /_yardoc/ 26 | /doc/ 27 | /rdoc/ 28 | 29 | ## Environment normalisation: 30 | /.bundle/ 31 | /vendor/bundle 32 | /lib/bundler/man/ 33 | 34 | # for a library or gem, you might want to ignore these files since the code is 35 | # intended to run in multiple environments; otherwise, check them in: 36 | Gemfile.lock 37 | .ruby-version 38 | .ruby-gemset 39 | 40 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 41 | .rvmrc -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | ruby 3.3.6 2 | -------------------------------------------------------------------------------- /2015/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | up = input.scan(/\(/).count 7 | down = input.scan(/\)/).count 8 | 9 | floor = up - down 10 | 11 | puts floor 12 | -------------------------------------------------------------------------------- /2015/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | # Could be better 7 | input.chars.each_with_index.inject(0) do |floor, (character, index)| 8 | if character == "(" 9 | floor += 1 10 | else 11 | floor -= 1 12 | end 13 | 14 | if floor < 0 15 | puts index + 1 16 | break 17 | end 18 | 19 | floor 20 | end 21 | -------------------------------------------------------------------------------- /2015/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | presents = File.readlines(file_path) 5 | 6 | total = 0 7 | 8 | presents.each do |present| 9 | sides = present.split("x").map(&:to_i) 10 | 11 | areas = sides.combination(2).map do |side_one, side_two| 12 | side_one * side_two 13 | end 14 | 15 | total += areas.inject(:+) * 2 16 | total += areas.min 17 | end 18 | 19 | puts total 20 | -------------------------------------------------------------------------------- /2015/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | presents = File.readlines(file_path) 5 | 6 | total = 0 7 | 8 | presents.each do |present| 9 | sides = present.split("x").map(&:to_i) 10 | 11 | # Wrap 12 | total += sides.sort.min(2).inject(:+) * 2 13 | # Bow 14 | total += sides.inject(:*) 15 | end 16 | 17 | puts total 18 | -------------------------------------------------------------------------------- /2015/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | x = 0 9 | y = 0 10 | 11 | homes = Set.new 12 | homes.add("#{x},#{y}") 13 | 14 | input.chars.each do |direction| 15 | case direction 16 | when '>' 17 | x += 1 18 | when '<' 19 | x -= 1 20 | when '^' 21 | y -= 1 22 | when 'v' 23 | y += 1 24 | end 25 | 26 | homes.add("#{x},#{y}") 27 | end 28 | 29 | puts homes.count 30 | -------------------------------------------------------------------------------- /2015/day-04/README.md: -------------------------------------------------------------------------------- 1 | ## Day 4: The Ideal Stocking Stuffer 2 | 3 | Santa needs help mining some AdventCoins (very similar to bitcoins) to use as gifts for all the economically forward-thinking little girls and boys. 4 | 5 | To do this, he needs to find MD5 hashes which, in hexadecimal, start with at least five zeroes. The input to the MD5 hash is some secret key (your puzzle input, given below) followed by a number in decimal. To mine AdventCoins, you must find Santa the lowest positive number (no leading zeroes: 1, 2, 3, ...) that produces such a hash. 6 | 7 | For example: 8 | 9 | * If your secret key is abcdef, the answer is 609043, because the MD5 hash of abcdef609043 starts with five zeroes (000001dbbfa...), and it is the lowest such number to do so. 10 | * If your secret key is pqrstuv, the lowest number it combines with to make an MD5 hash starting with five zeroes is 1048970; that is, the MD5 hash of pqrstuv1048970 looks like 000006136ef.... 11 | -------------------------------------------------------------------------------- /2015/day-04/day-04-input.txt: -------------------------------------------------------------------------------- 1 | yzbqklnj -------------------------------------------------------------------------------- /2015/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'digest' 4 | 5 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | number = 0 9 | 10 | while true 11 | digest = Digest::MD5.hexdigest("#{input}#{number}") 12 | break if digest =~ /\A00000/ 13 | 14 | number += 1 15 | end 16 | 17 | puts number -------------------------------------------------------------------------------- /2015/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'digest' 4 | 5 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | number = 0 9 | 10 | while true 11 | digest = Digest::MD5.hexdigest("#{input}#{number}") 12 | break if digest =~ /\A000000/ 13 | 14 | number += 1 15 | end 16 | 17 | puts number -------------------------------------------------------------------------------- /2015/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | strings = File.readlines(file_path) 5 | 6 | strings.reject! { |string| string =~ /ab|cd|pq|xy/ } 7 | 8 | strings.reject! do |string| 9 | string.chars.select { |char| %w(a e i o u).include?(char) }.count < 3 10 | end 11 | 12 | strings.select! do |string| 13 | string.chars.each_cons(2).any? { |a, b| a == b } 14 | end 15 | 16 | puts strings.count 17 | -------------------------------------------------------------------------------- /2015/day-05/day-05-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | strings = File.readlines(file_path) 5 | 6 | strings.select! do |string| 7 | string.chars.each_cons(3).any? { |a, _b, c| a == c } 8 | end 9 | 10 | # Could be better 11 | strings.select! do |string| 12 | (string.length - 3).times.any? do |index| 13 | pair = string[index, 2] 14 | 15 | string[(index + 2)..-1].chars. 16 | each_cons(2). 17 | map(&:join). 18 | any? { |pair2| pair2 == pair } 19 | end 20 | end 21 | 22 | puts strings.count 23 | -------------------------------------------------------------------------------- /2015/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | lines = File.readlines(file_path).map(&:strip) 5 | 6 | code_characters = lines.map(&:length).inject(:+) 7 | memory_characters = lines.map { |line| eval(line).length }.inject(:+) 8 | 9 | puts code_characters - memory_characters 10 | -------------------------------------------------------------------------------- /2015/day-08/day-08-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | lines = File.readlines(file_path).map(&:strip) 5 | 6 | code_characters = lines.map(&:length).inject(:+) 7 | encoded_characters = lines.map(&:inspect).map(&:length).inject(:+) 8 | 9 | puts encoded_characters - code_characters 10 | -------------------------------------------------------------------------------- /2015/day-09/day-09-input.txt: -------------------------------------------------------------------------------- 1 | AlphaCentauri to Snowdin = 66 2 | AlphaCentauri to Tambi = 28 3 | AlphaCentauri to Faerun = 60 4 | AlphaCentauri to Norrath = 34 5 | AlphaCentauri to Straylight = 34 6 | AlphaCentauri to Tristram = 3 7 | AlphaCentauri to Arbre = 108 8 | Snowdin to Tambi = 22 9 | Snowdin to Faerun = 12 10 | Snowdin to Norrath = 91 11 | Snowdin to Straylight = 121 12 | Snowdin to Tristram = 111 13 | Snowdin to Arbre = 71 14 | Tambi to Faerun = 39 15 | Tambi to Norrath = 113 16 | Tambi to Straylight = 130 17 | Tambi to Tristram = 35 18 | Tambi to Arbre = 40 19 | Faerun to Norrath = 63 20 | Faerun to Straylight = 21 21 | Faerun to Tristram = 57 22 | Faerun to Arbre = 83 23 | Norrath to Straylight = 9 24 | Norrath to Tristram = 50 25 | Norrath to Arbre = 60 26 | Straylight to Tristram = 27 27 | Straylight to Arbre = 81 28 | Tristram to Arbre = 90 -------------------------------------------------------------------------------- /2015/day-09/day-09-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # It's only 8 nodes (locations), so we can brute force with no problem :) 4 | # !8 = 40320 possible paths 5 | 6 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 7 | distances = File.readlines(file_path) 8 | 9 | locations = Hash.new { |hash, key| hash[key] = {} } 10 | 11 | distances.each do |distance| 12 | from, _, to = distance.scan(/[A-z]+/) 13 | length = distance.scan(/\d+/)[0].to_i 14 | 15 | locations[from][to] = length 16 | locations[to][from] = length 17 | end 18 | 19 | route_lengths = locations.keys.permutation.map do |path| 20 | path.each_cons(2).inject(0) do |total, (from, to)| 21 | total + locations[from][to] 22 | end 23 | end 24 | 25 | puts route_lengths.min 26 | -------------------------------------------------------------------------------- /2015/day-09/day-09-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # It's only 8 nodes (locations), so we can brute force with no problem :) 4 | # !8 = 40320 possible paths 5 | 6 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 7 | distances = File.readlines(file_path) 8 | 9 | locations = Hash.new { |hash, key| hash[key] = {} } 10 | 11 | distances.each do |distance| 12 | from, _, to = distance.scan(/[A-z]+/) 13 | length = distance.scan(/\d+/)[0].to_i 14 | 15 | locations[from][to] = length 16 | locations[to][from] = length 17 | end 18 | 19 | route_lengths = locations.keys.permutation.map do |path| 20 | path.each_cons(2).inject(0) do |total, (from, to)| 21 | total + locations[from][to] 22 | end 23 | end 24 | 25 | puts route_lengths.max 26 | -------------------------------------------------------------------------------- /2015/day-10/day-10-input.txt: -------------------------------------------------------------------------------- 1 | 1113222113 -------------------------------------------------------------------------------- /2015/day-10/day-10-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | numbers = input.chars.map(&:to_i) 7 | 8 | 40.times do 9 | numbers = numbers.slice_when { |before, after| before != after }. 10 | flat_map { |numbers| [numbers.count, numbers.first] } 11 | end 12 | 13 | puts numbers.length 14 | -------------------------------------------------------------------------------- /2015/day-10/day-10-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | numbers = input.chars.map(&:to_i) 7 | 8 | 50.times do 9 | numbers = numbers.slice_when { |before, after| before != after }. 10 | flat_map { |numbers| [numbers.count, numbers.first] } 11 | end 12 | 13 | puts numbers.length 14 | -------------------------------------------------------------------------------- /2015/day-11/day-11-input.txt: -------------------------------------------------------------------------------- 1 | hxbxwxba -------------------------------------------------------------------------------- /2015/day-11/day-11-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | password = File.read(file_path) 5 | 6 | def increasing_straight?(password) 7 | password.chars.each_cons(3).any? do |a, b, c| 8 | a.ord + 1 == b.ord && a.ord + 2 == c.ord 9 | end 10 | end 11 | 12 | def two_pairs?(password) 13 | password.scan(/(.)\1/).count >= 2 14 | end 15 | 16 | def excludes_confusing_characters(password) 17 | password.scan(/[iol]/).empty? 18 | end 19 | 20 | def valid_password?(password) 21 | increasing_straight?(password) && 22 | two_pairs?(password) && 23 | excludes_confusing_characters(password) 24 | end 25 | 26 | next_password = 1 27 | 28 | while next_password != 0 29 | password.succ! 30 | 31 | next_password -= 1 if valid_password?(password) 32 | end 33 | 34 | puts password 35 | -------------------------------------------------------------------------------- /2015/day-11/day-11-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | password = File.read(file_path) 5 | 6 | def increasing_straight?(password) 7 | password.chars.each_cons(3).any? do |a, b, c| 8 | a.ord + 1 == b.ord && a.ord + 2 == c.ord 9 | end 10 | end 11 | 12 | def two_pairs?(password) 13 | password.scan(/(.)\1/).count >= 2 14 | end 15 | 16 | def excludes_confusing_characters(password) 17 | password.scan(/[iol]/).empty? 18 | end 19 | 20 | def valid_password?(password) 21 | increasing_straight?(password) && 22 | two_pairs?(password) && 23 | excludes_confusing_characters(password) 24 | end 25 | 26 | next_password = 2 27 | 28 | while next_password != 0 29 | password.succ! 30 | 31 | next_password -= 1 if valid_password?(password) 32 | end 33 | 34 | puts password 35 | -------------------------------------------------------------------------------- /2015/day-12/day-12-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'json' 4 | 5 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | json = JSON.parse(input) 9 | 10 | def find_numbers(input) 11 | case input 12 | when Array 13 | input.flat_map { |value| find_numbers(value) }.compact 14 | when Hash 15 | find_numbers(input.values).compact 16 | when String 17 | [nil] 18 | when Fixnum 19 | [input] 20 | end 21 | end 22 | 23 | puts find_numbers(json).inject(:+) 24 | -------------------------------------------------------------------------------- /2015/day-12/day-12-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'json' 4 | 5 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | json = JSON.parse(input) 9 | 10 | def find_numbers(input) 11 | case input 12 | when Array 13 | input.flat_map { |value| find_numbers(value) }.compact 14 | when Hash 15 | if input.values.include? "red" 16 | [nil] 17 | else 18 | find_numbers(input.values).compact 19 | end 20 | when String 21 | [nil] 22 | when Fixnum 23 | [input] 24 | end 25 | end 26 | 27 | puts find_numbers(json).inject(:+) 28 | -------------------------------------------------------------------------------- /2015/day-14/day-14-input.txt: -------------------------------------------------------------------------------- 1 | Rudolph can fly 22 km/s for 8 seconds, but then must rest for 165 seconds. 2 | Cupid can fly 8 km/s for 17 seconds, but then must rest for 114 seconds. 3 | Prancer can fly 18 km/s for 6 seconds, but then must rest for 103 seconds. 4 | Donner can fly 25 km/s for 6 seconds, but then must rest for 145 seconds. 5 | Dasher can fly 11 km/s for 12 seconds, but then must rest for 125 seconds. 6 | Comet can fly 21 km/s for 6 seconds, but then must rest for 121 seconds. 7 | Blitzen can fly 18 km/s for 3 seconds, but then must rest for 50 seconds. 8 | Vixen can fly 20 km/s for 4 seconds, but then must rest for 75 seconds. 9 | Dancer can fly 7 km/s for 20 seconds, but then must rest for 119 seconds. -------------------------------------------------------------------------------- /2015/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | reindeers = File.readlines(file_path) 5 | 6 | seconds = 2503 7 | 8 | class Reindeer 9 | attr_reader :speed, :duration, :rest, :distance 10 | 11 | def initialize(speed, duration, rest) 12 | @speed = speed 13 | @duration = duration 14 | @rest = rest 15 | @distance = 0 16 | end 17 | 18 | def race(seconds) 19 | while seconds > 0 20 | @distance += speed * [seconds, duration].min 21 | seconds -= duration 22 | seconds -= rest 23 | end 24 | 25 | self 26 | end 27 | end 28 | 29 | reindeers.map! do |reindeer| 30 | speed = reindeer.match(/(\d+) km\/s/)[1].to_i 31 | duration = reindeer.match(/(\d+) seconds,/)[1].to_i 32 | resting_duration = reindeer.match(/(\d+) seconds\./)[1].to_i 33 | 34 | Reindeer.new(speed, duration, resting_duration).race(seconds) 35 | end 36 | 37 | puts reindeers.map(&:distance).max 38 | -------------------------------------------------------------------------------- /2015/day-15/day-15-input.txt: -------------------------------------------------------------------------------- 1 | Sprinkles: capacity 2, durability 0, flavor -2, texture 0, calories 3 2 | Butterscotch: capacity 0, durability 5, flavor -3, texture 0, calories 3 3 | Chocolate: capacity 0, durability 0, flavor 5, texture -1, calories 8 4 | Candy: capacity 0, durability -1, flavor 0, texture 5, calories 8 -------------------------------------------------------------------------------- /2015/day-17/day-17-input.txt: -------------------------------------------------------------------------------- 1 | 43 2 | 3 3 | 4 4 | 10 5 | 21 6 | 44 7 | 4 8 | 6 9 | 47 10 | 41 11 | 34 12 | 17 13 | 17 14 | 44 15 | 36 16 | 31 17 | 46 18 | 9 19 | 27 20 | 38 -------------------------------------------------------------------------------- /2015/day-17/day-17-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-17-input.txt", __FILE__) 4 | containers = File.readlines(file_path) 5 | 6 | containers.map!(&:to_i) 7 | liters = 150 8 | 9 | combinations = [] 10 | 11 | 1.upto(containers.count) do |container_count| 12 | combos = containers.combination(container_count).select do |combination| 13 | combination.inject(:+) == liters 14 | end 15 | 16 | combinations.concat combos 17 | end 18 | 19 | puts combinations.count 20 | -------------------------------------------------------------------------------- /2015/day-17/day-17-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-17-input.txt", __FILE__) 4 | containers = File.readlines(file_path) 5 | 6 | containers.map!(&:to_i) 7 | liters = 150 8 | 9 | combinations = [] 10 | 11 | 1.upto(containers.count) do |container_count| 12 | combos = containers.combination(container_count).select do |combination| 13 | combination.inject(:+) == liters 14 | end 15 | 16 | combinations.concat combos 17 | end 18 | 19 | counts = combinations.map(&:count) 20 | min_count = counts.min 21 | 22 | puts counts.select { |count| count == min_count }.count 23 | -------------------------------------------------------------------------------- /2015/day-20/day-20-input.txt: -------------------------------------------------------------------------------- 1 | 34000000 -------------------------------------------------------------------------------- /2015/day-20/day-20-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | target = File.read(file_path).to_i 5 | 6 | houses = Hash.new(0) 7 | 8 | 1.upto(target / 10) do |elf| 9 | 1.upto(target / 10 / elf) do |number| 10 | houses[number * elf] += elf * 10 11 | end 12 | end 13 | 14 | lowest_house = houses.find do |_house, presents| 15 | presents >= target 16 | end 17 | 18 | puts lowest_house 19 | -------------------------------------------------------------------------------- /2015/day-20/day-20-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | target = File.read(file_path).to_i 5 | 6 | houses = Hash.new(0) 7 | 8 | 1.upto(target / 10) do |elf| 9 | 1.upto([50, target / 10 / elf].min) do |number| 10 | houses[number * elf] += elf * 11 11 | end 12 | end 13 | 14 | lowest_house = houses.find do |_house, presents| 15 | presents >= target 16 | end 17 | 18 | puts lowest_house 19 | -------------------------------------------------------------------------------- /2015/day-21/day-21-input.txt: -------------------------------------------------------------------------------- 1 | Hit Points: 104 2 | Damage: 8 3 | Armor: 1 -------------------------------------------------------------------------------- /2015/day-22/day-22-input.txt: -------------------------------------------------------------------------------- 1 | Hit Points: 55 2 | Damage: 8 3 | -------------------------------------------------------------------------------- /2015/day-23/day-23-input.txt: -------------------------------------------------------------------------------- 1 | jio a, +18 2 | inc a 3 | tpl a 4 | inc a 5 | tpl a 6 | tpl a 7 | tpl a 8 | inc a 9 | tpl a 10 | inc a 11 | tpl a 12 | inc a 13 | inc a 14 | tpl a 15 | tpl a 16 | tpl a 17 | inc a 18 | jmp +22 19 | tpl a 20 | inc a 21 | tpl a 22 | inc a 23 | inc a 24 | tpl a 25 | inc a 26 | tpl a 27 | inc a 28 | inc a 29 | tpl a 30 | tpl a 31 | inc a 32 | inc a 33 | tpl a 34 | inc a 35 | inc a 36 | tpl a 37 | inc a 38 | inc a 39 | tpl a 40 | jio a, +8 41 | inc b 42 | jie a, +4 43 | tpl a 44 | inc a 45 | jmp +2 46 | hlf a 47 | jmp -7 -------------------------------------------------------------------------------- /2015/day-24/day-24-input.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 3 3 | 5 4 | 11 5 | 13 6 | 17 7 | 19 8 | 23 9 | 29 10 | 31 11 | 37 12 | 41 13 | 43 14 | 47 15 | 53 16 | 59 17 | 67 18 | 71 19 | 73 20 | 79 21 | 83 22 | 89 23 | 97 24 | 101 25 | 103 26 | 107 27 | 109 28 | 113 -------------------------------------------------------------------------------- /2015/day-24/day-24-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-24-input.txt", __FILE__) 4 | presents = File.readlines(file_path) 5 | 6 | presents.map!(&:to_i) 7 | 8 | groups = 3 9 | target = presents.inject(:+) / groups 10 | min_qe = nil 11 | 12 | 1.upto(presents.size / groups) do |group_size| 13 | groups = presents.combination(group_size). 14 | select { |group| group.inject(:+) == target } 15 | 16 | groups.each do |group| 17 | qe = group.inject(:*) 18 | min_qe = [qe, min_qe].compact.min 19 | end 20 | 21 | break if min_qe 22 | end 23 | 24 | puts min_qe 25 | -------------------------------------------------------------------------------- /2015/day-24/day-24-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-24-input.txt", __FILE__) 4 | presents = File.readlines(file_path) 5 | 6 | presents.map!(&:to_i) 7 | 8 | groups = 4 9 | target = presents.inject(:+) / groups 10 | min_qe = nil 11 | 12 | 1.upto(presents.size / groups) do |group_size| 13 | groups = presents.combination(group_size). 14 | select { |group| group.inject(:+) == target } 15 | 16 | groups.each do |group| 17 | qe = group.inject(:*) 18 | min_qe = [qe, min_qe].compact.min 19 | end 20 | 21 | break if min_qe 22 | end 23 | 24 | puts min_qe 25 | -------------------------------------------------------------------------------- /2015/day-25/day-25-input.txt: -------------------------------------------------------------------------------- 1 | To continue, please consult the code grid in the manual. Enter the code at row 2978, column 3083. 2 | -------------------------------------------------------------------------------- /2015/day-25/day-25-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | grid = [[], []] 4 | 5 | prev_code = 20151125 6 | grid[1][1] = prev_code 7 | 8 | row = 1 9 | col = 1 10 | 11 | while !(row == 2978 && col == 3083) 12 | col += 1 13 | row -= 1 14 | 15 | if row == 0 16 | row = grid.length 17 | col = 1 18 | grid << [] 19 | end 20 | 21 | code = (prev_code * 252533) % 33554393 22 | prev_code = code 23 | 24 | grid[row][col] = code 25 | end 26 | 27 | puts grid[row][col] 28 | -------------------------------------------------------------------------------- /2016/day-01/day-01-input.txt: -------------------------------------------------------------------------------- 1 | R1, R3, L2, L5, L2, L1, R3, L4, R2, L2, L4, R2, L1, R1, L2, R3, L1, L4, R2, L5, R3, R4, L1, R2, L1, R3, L4, R5, L4, L5, R5, L3, R2, L3, L3, R1, R3, L4, R2, R5, L4, R1, L1, L1, R5, L2, R1, L2, R188, L5, L3, R5, R1, L2, L4, R3, R5, L3, R3, R45, L4, R4, R72, R2, R3, L1, R1, L1, L1, R192, L1, L1, L1, L4, R1, L2, L5, L3, R5, L3, R3, L4, L3, R1, R4, L2, R2, R3, L5, R3, L1, R1, R4, L2, L3, R1, R3, L4, L3, L4, L2, L2, R1, R3, L5, L1, R4, R2, L4, L1, R3, R3, R1, L5, L2, R4, R4, R2, R1, R5, R5, L4, L1, R5, R3, R4, R5, R3, L1, L2, L4, R1, R4, R5, L2, L3, R4, L4, R2, L2, L4, L2, R5, R1, R4, R3, R5, L4, L4, L5, L5, R3, R4, L1, L3, R2, L2, R1, L3, L5, R5, R5, R3, L4, L2, R4, R5, R1, R4, L3 -------------------------------------------------------------------------------- /2016/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | dir = 0 7 | 8 | x = 0 9 | y = 0 10 | 11 | input.gsub(",", "").split.each do |cmd| 12 | if cmd[0] == "L" 13 | dir -= 1 14 | else # R 15 | dir += 1 16 | end 17 | 18 | dir %= 4 19 | 20 | blocks = cmd[1..-1].to_i 21 | 22 | case dir 23 | when 0 24 | y += blocks 25 | when 1 26 | x += blocks 27 | when 2 28 | y -= blocks 29 | when 3 30 | x -= blocks 31 | end 32 | end 33 | 34 | puts x.abs + y.abs 35 | -------------------------------------------------------------------------------- /2016/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | keys = [ 7 | [1, 2, 3], 8 | [4, 5, 6], 9 | [7, 8, 9] 10 | ] 11 | 12 | x = 1 13 | y = 1 14 | 15 | pin = "" 16 | 17 | input.split("\n").each do |seq| 18 | seq.chars.each do |cmd| 19 | case cmd 20 | when 'U' 21 | y = [y - 1, 0].max 22 | when 'D' 23 | y = [y + 1, 2].min 24 | when 'L' 25 | x = [x - 1, 0].max 26 | when 'R' 27 | x = [x + 1, 2].min 28 | end 29 | end 30 | 31 | pin << keys[y][x].to_s 32 | end 33 | 34 | puts pin 35 | -------------------------------------------------------------------------------- /2016/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | keys = [ 7 | [nil, nil, 1, nil, nil], 8 | [nil, 2, 3, 4, nil], 9 | [5, 6, 7, 8, 9], 10 | [nil, 'A', 'B', 'C', nil], 11 | [nil, nil, 'D', nil, nil] 12 | ] 13 | 14 | x = 0 15 | y = 2 16 | 17 | pin = "" 18 | 19 | input.split("\n").each do |seq| 20 | seq.chars.each do |cmd| 21 | x2 = x 22 | y2 = y 23 | 24 | case cmd 25 | when 'U' 26 | y2 = [y - 1, 0].max 27 | when 'D' 28 | y2 = [y + 1, 4].min 29 | when 'L' 30 | x2 = [x - 1, 0].max 31 | when 'R' 32 | x2 = [x + 1, 4].min 33 | end 34 | 35 | if keys[y2][x2] 36 | x = x2 37 | y = y2 38 | end 39 | end 40 | 41 | pin << keys[y][x].to_s 42 | end 43 | 44 | puts pin 45 | -------------------------------------------------------------------------------- /2016/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | triangles = input.split("\n").map { |triangle| triangle.split.map(&:to_i).sort } 7 | 8 | puts triangles.count { |sides| sides[0] + sides[1] > sides[2] } 9 | -------------------------------------------------------------------------------- /2016/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | columns = input.split("\n").map { |triangle| triangle.split.map(&:to_i) }.transpose 7 | 8 | triangles = columns.flat_map { |column| column.each_slice(3).map(&:sort) } 9 | 10 | puts triangles.count { |sides| sides[0] + sides[1] > sides[2] } 11 | -------------------------------------------------------------------------------- /2016/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | Room = Struct.new(:name, :id, :checksum) 7 | 8 | rooms = input.gsub('-', '').split("\n").map do |room| 9 | name = room.match(/[a-z]*/)[0] 10 | id = room.match(/\d{3}/)[0].to_i 11 | checksum = room.match(/\[([a-z]{5})\]/)[1] 12 | 13 | Room.new(name, id, checksum) 14 | end 15 | 16 | real_rooms = rooms.select do |room| 17 | chars = room.name.chars 18 | 19 | counts = {} 20 | 21 | chars.uniq.each do |char| 22 | counts[char] = room.name.count(char) 23 | end 24 | 25 | expected_checksum = counts. 26 | sort_by { |char, count| [-count, char] }. 27 | first(5).map(&:first).join 28 | 29 | expected_checksum == room.checksum 30 | end 31 | 32 | puts real_rooms.inject(0) { |sum, room| sum + room.id } 33 | -------------------------------------------------------------------------------- /2016/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.split("\n").map do |room| 7 | name = room.match(/[a-z-]*/)[0] 8 | id = room.match(/\d{3}/)[0].to_i 9 | 10 | cipher = ('a'..'z').to_a.rotate(id % 26) 11 | 12 | decrypted_name = name.tr(('a'..'z').to_a.join, cipher.join) 13 | 14 | puts "#{decrypted_name} #{id}" if decrypted_name.include?("north") 15 | end 16 | -------------------------------------------------------------------------------- /2016/day-05/day-05-input.txt: -------------------------------------------------------------------------------- 1 | ffykfhsq -------------------------------------------------------------------------------- /2016/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'digest' 4 | 5 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | i = 0 9 | 10 | pw = [] 11 | 12 | while pw.length < 8 do 13 | digest = Digest::MD5.hexdigest(input + i.to_s) 14 | 15 | pw << digest[5] if digest.start_with?("00000") 16 | 17 | i += 1 18 | end 19 | 20 | puts pw.join 21 | -------------------------------------------------------------------------------- /2016/day-05/day-05-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'digest' 4 | 5 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | i = 0 9 | 10 | pw = "........" 11 | 12 | loop do 13 | digest = Digest::MD5.hexdigest(input + i.to_s) 14 | 15 | if digest.start_with?("00000") && digest[5].match(/[0-7]/) 16 | pos = digest[5].to_i 17 | 18 | if pw[pos] == '.' 19 | pw[pos] = digest[6] 20 | puts pw 21 | end 22 | 23 | break unless pw.match(/\./) 24 | end 25 | 26 | i += 1 27 | end 28 | 29 | puts pw 30 | -------------------------------------------------------------------------------- /2016/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | message = Array.new(lines.first.length) { 9 | Hash.new { |h, k| h[k] = 0 } 10 | } 11 | 12 | lines.each do |line| 13 | line.chars.each.with_index do |char, index| 14 | message[index][char] += 1 15 | end 16 | end 17 | 18 | puts message.map { |chars| 19 | chars.sort_by { |char, count| count }.last.first 20 | }.join 21 | -------------------------------------------------------------------------------- /2016/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | message = Array.new(lines.first.length) { 9 | Hash.new { |h, k| h[k] = 0 } 10 | } 11 | 12 | lines.each do |line| 13 | line.chars.each.with_index do |char, index| 14 | message[index][char] += 1 15 | end 16 | end 17 | 18 | puts message.map { |chars| 19 | chars.sort_by { |char, count| count }.first.first 20 | }.join 21 | -------------------------------------------------------------------------------- /2016/day-07/day-07-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | def abba?(text) 9 | text.chars.each_cons(4) do |chars| 10 | str = chars.join 11 | next if str[0] == str[1] 12 | if str[0..1] == str[2..3].chars.reverse.join 13 | return true 14 | end 15 | end 16 | 17 | false 18 | end 19 | 20 | tls = lines.select do |line| 21 | strings = line.split(/\[|\]/) 22 | 23 | sequences, hypernets = strings.partition.with_index do |str, idx| 24 | idx.even? 25 | end 26 | 27 | sequences.any?{ |seq| abba?(seq) } && 28 | !hypernets.any?{ |seq| abba?(seq) } 29 | end 30 | 31 | puts tls.count 32 | -------------------------------------------------------------------------------- /2016/day-07/day-07-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | def aba(text) 9 | result = [] 10 | 11 | text.chars.each_cons(3) do |chars| 12 | str = chars.join 13 | 14 | result << str if str[0] == str[2] 15 | end 16 | 17 | result 18 | end 19 | 20 | def bab(text) 21 | aba(text).map do |aba| 22 | aba[1] + aba[0] + aba[1] 23 | end 24 | end 25 | 26 | ssl = lines.select { |line| 27 | strings = line.split(/\[|\]/) 28 | 29 | sequences, hypernets = strings.partition.with_index do |str, idx| 30 | idx.even? 31 | end 32 | 33 | abas = sequences.flat_map { |str| aba(str) } 34 | babs = hypernets.flat_map { |str| bab(str) } 35 | 36 | (abas & babs).any? 37 | } 38 | 39 | puts ssl.count 40 | -------------------------------------------------------------------------------- /2016/day-09/day-09-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | idx = 0 7 | length = 0 8 | 9 | while idx < input.length do 10 | if input[idx] == '(' 11 | marker = input[idx..-1].match(/\(([0-9x]*)\)/)[1] 12 | 13 | chars, repeat = marker.split("x").map(&:to_i) 14 | 15 | length += chars * repeat 16 | idx += chars + marker.length + 2 17 | else 18 | length += 1 19 | idx += 1 20 | end 21 | end 22 | 23 | puts length 24 | -------------------------------------------------------------------------------- /2016/day-09/day-09-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | def decompress(string) 7 | idx = 0 8 | length = 0 9 | 10 | while idx < string.length do 11 | if string[idx] == '(' 12 | marker = string[idx..-1].match(/\(([0-9x]*)\)/)[1] 13 | 14 | chars, repeat = marker.split("x").map(&:to_i) 15 | 16 | sub_start = idx + marker.length + 2 17 | substring = string[sub_start...sub_start+chars] 18 | 19 | length += decompress(substring) * repeat 20 | idx += chars + marker.length + 2 21 | else 22 | length += 1 23 | idx += 1 24 | end 25 | end 26 | 27 | length 28 | end 29 | 30 | puts decompress(input) 31 | -------------------------------------------------------------------------------- /2016/day-11/day-11-input-part-2.txt: -------------------------------------------------------------------------------- 1 | The first floor contains a thulium generator, a thulium-compatible microchip, a plutonium generator, an elerium generator, an elerium-compatible microchip, a dilithium generator, a dilithium-compatible microchip, and a strontium generator. 2 | The second floor contains a plutonium-compatible microchip and a strontium-compatible microchip. 3 | The third floor contains a promethium generator, a promethium-compatible microchip, a ruthenium generator, and a ruthenium-compatible microchip. 4 | The fourth floor contains nothing relevant. -------------------------------------------------------------------------------- /2016/day-11/day-11-input.txt: -------------------------------------------------------------------------------- 1 | The first floor contains a thulium generator, a thulium-compatible microchip, a plutonium generator, and a strontium generator. 2 | The second floor contains a plutonium-compatible microchip and a strontium-compatible microchip. 3 | The third floor contains a promethium generator, a promethium-compatible microchip, a ruthenium generator, and a ruthenium-compatible microchip. 4 | The fourth floor contains nothing relevant. -------------------------------------------------------------------------------- /2016/day-12/day-12-input.txt: -------------------------------------------------------------------------------- 1 | cpy 1 a 2 | cpy 1 b 3 | cpy 26 d 4 | jnz c 2 5 | jnz 1 5 6 | cpy 7 c 7 | inc d 8 | dec c 9 | jnz c -2 10 | cpy a c 11 | inc a 12 | dec b 13 | jnz b -2 14 | cpy c b 15 | dec d 16 | jnz d -6 17 | cpy 13 c 18 | cpy 14 d 19 | inc a 20 | dec d 21 | jnz d -2 22 | dec c 23 | jnz c -5 -------------------------------------------------------------------------------- /2016/day-12/day-12-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | instructions = input.split("\n") 7 | 8 | reg = Hash.new { |hash, key| hash[key] = 0 } 9 | 10 | i = 0 11 | 12 | while i < instructions.length 13 | cmd, arg1, arg2 = instructions[i].split(" ") 14 | 15 | if arg1 =~ /\d/ 16 | val = arg1.to_i 17 | else 18 | val = reg[arg1] 19 | end 20 | 21 | case cmd 22 | when 'cpy' 23 | reg[arg2] = val 24 | when 'jnz' 25 | if val != 0 26 | i += arg2.to_i 27 | next 28 | end 29 | when 'inc' 30 | reg[arg1] += 1 31 | when 'dec' 32 | reg[arg1] -= 1 33 | end 34 | 35 | i += 1 36 | end 37 | 38 | puts reg['a'] 39 | -------------------------------------------------------------------------------- /2016/day-12/day-12-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | instructions = input.split("\n") 7 | 8 | reg = { 9 | "a" => 0, 10 | "b" => 0, 11 | "c" => 1, 12 | "d" => 0 13 | } 14 | 15 | i = 0 16 | 17 | while i < instructions.length 18 | cmd, arg1, arg2 = instructions[i].split(" ") 19 | 20 | if arg1 =~ /\d/ 21 | val = arg1.to_i 22 | else 23 | val = reg[arg1] 24 | end 25 | 26 | case cmd 27 | when 'cpy' 28 | reg[arg2] = val 29 | when 'jnz' 30 | if val != 0 31 | i += arg2.to_i 32 | next 33 | end 34 | when 'inc' 35 | reg[arg1] += 1 36 | when 'dec' 37 | reg[arg1] -= 1 38 | end 39 | 40 | i += 1 41 | end 42 | 43 | puts reg['a'] 44 | -------------------------------------------------------------------------------- /2016/day-13/day-13-input.txt: -------------------------------------------------------------------------------- 1 | 1350 -------------------------------------------------------------------------------- /2016/day-14/day-14-input.txt: -------------------------------------------------------------------------------- 1 | cuanljph -------------------------------------------------------------------------------- /2016/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'digest' 4 | require 'set' 5 | 6 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 7 | input = File.read(file_path) 8 | 9 | triples = [] 10 | keys = Set.new 11 | 12 | number = 0 13 | 14 | while keys.length < 64 15 | digest = Digest::MD5.hexdigest("#{input}#{number}") 16 | 17 | five_match = digest =~ /(.)\1\1\1\1/ 18 | if five_match 19 | triples.each do |triple, pattern| 20 | if digest[five_match] == pattern[0] && triple + 1000 >= number 21 | keys.add(triple) 22 | puts triple if keys.count == 64 23 | puts [keys.count, triple].join(", ") 24 | end 25 | end 26 | end 27 | 28 | triple_match = digest =~ /(.)\1\1/ 29 | triples << [number, digest[triple_match]] if triple_match 30 | 31 | number += 1 32 | end 33 | -------------------------------------------------------------------------------- /2016/day-14/day-14-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'digest' 4 | require 'set' 5 | 6 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 7 | input = File.read(file_path) 8 | 9 | triples = [] 10 | keys = Set.new 11 | 12 | number = 0 13 | 14 | while keys.length < 64 15 | digest = Digest::MD5.hexdigest("#{input}#{number}") 16 | 17 | 2016.times do 18 | digest = Digest::MD5.hexdigest(digest) 19 | end 20 | 21 | five_match = digest =~ /(.)\1\1\1\1/ 22 | if five_match 23 | triples.each do |triple, pattern| 24 | if digest[five_match] == pattern[0] && triple + 1000 >= number 25 | keys.add(triple) 26 | puts triple if keys.count == 64 27 | puts [keys.count, triple].join(", ") 28 | end 29 | end 30 | end 31 | 32 | triple_match = digest =~ /(.)\1\1/ 33 | triples << [number, digest[triple_match]] if triple_match 34 | 35 | number += 1 36 | end 37 | -------------------------------------------------------------------------------- /2016/day-15/day-15-input.txt: -------------------------------------------------------------------------------- 1 | Disc #1 has 13 positions; at time=0, it is at position 11. 2 | Disc #2 has 5 positions; at time=0, it is at position 0. 3 | Disc #3 has 17 positions; at time=0, it is at position 11. 4 | Disc #4 has 3 positions; at time=0, it is at position 0. 5 | Disc #5 has 7 positions; at time=0, it is at position 2. 6 | Disc #6 has 19 positions; at time=0, it is at position 17. -------------------------------------------------------------------------------- /2016/day-15/day-15-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-15-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | discs = [] 7 | 8 | discs = input.split("\n").map.with_index do |disc, idx| 9 | positions = disc.match(/(\d*) positions/)[1].to_i 10 | start = disc.match(/position (\d*)/)[1].to_i 11 | 12 | [idx, positions, start] 13 | end 14 | 15 | def fall_through?(time, discs) 16 | discs.all? do |disc| 17 | (disc[0] + 1 + time + disc[2]) % disc[1] == 0 18 | end 19 | end 20 | 21 | time = 0 22 | 23 | while !fall_through?(time, discs) 24 | time += 1 25 | end 26 | 27 | puts time 28 | -------------------------------------------------------------------------------- /2016/day-15/day-15-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-15-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input << "\nDisc #7 has 11 positions; at time=0, it is at position 0." 7 | 8 | discs = [] 9 | 10 | discs = input.split("\n").map.with_index do |disc, idx| 11 | positions = disc.match(/(\d*) positions/)[1].to_i 12 | start = disc.match(/position (\d*)/)[1].to_i 13 | 14 | [idx, positions, start] 15 | end 16 | 17 | def fall_through?(time, discs) 18 | discs.all? do |disc| 19 | (disc[0] + 1 + time + disc[2]) % disc[1] == 0 20 | end 21 | end 22 | 23 | time = 0 24 | 25 | while !fall_through?(time, discs) 26 | time += 1 27 | end 28 | 29 | puts time 30 | -------------------------------------------------------------------------------- /2016/day-16/day-16-input.txt: -------------------------------------------------------------------------------- 1 | 11100010111110100 -------------------------------------------------------------------------------- /2016/day-16/day-16-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-16-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | goal = 272 7 | 8 | a = input.chars.map(&:to_i) 9 | 10 | while a.length < goal 11 | b = a.reverse.map do |bit| 12 | if bit == 0 13 | 1 14 | else 15 | 0 16 | end 17 | end 18 | 19 | a << 0 20 | a.concat b 21 | end 22 | 23 | a = a[0..(goal-1)] 24 | puts a.length 25 | 26 | sum = a 27 | 28 | while sum.length % 2 == 0 29 | next_sum = [] 30 | 31 | sum.each_slice(2) do |x, y| 32 | if x == y 33 | next_sum << 1 34 | else 35 | next_sum << 0 36 | end 37 | end 38 | 39 | sum = next_sum 40 | end 41 | 42 | puts sum.join 43 | -------------------------------------------------------------------------------- /2016/day-16/day-16-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-16-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | goal = 35651584 7 | 8 | a = input.chars.map(&:to_i) 9 | 10 | while a.length < goal 11 | b = a.reverse.map do |bit| 12 | if bit == 0 13 | 1 14 | else 15 | 0 16 | end 17 | end 18 | 19 | a << 0 20 | a.concat b 21 | end 22 | 23 | a = a[0..(goal-1)] 24 | puts a.length 25 | 26 | sum = a 27 | 28 | while sum.length % 2 == 0 29 | next_sum = [] 30 | 31 | sum.each_slice(2) do |x, y| 32 | if x == y 33 | next_sum << 1 34 | else 35 | next_sum << 0 36 | end 37 | end 38 | 39 | sum = next_sum 40 | end 41 | 42 | puts sum.join 43 | -------------------------------------------------------------------------------- /2016/day-17/day-17-input.txt: -------------------------------------------------------------------------------- 1 | ioramepc -------------------------------------------------------------------------------- /2016/day-18/day-18-input.txt: -------------------------------------------------------------------------------- 1 | .^^^.^.^^^.^.......^^.^^^^.^^^^..^^^^^.^.^^^..^^.^.^^..^.^..^^...^.^^.^^^...^^.^.^^^..^^^^.....^.... -------------------------------------------------------------------------------- /2016/day-18/day-18-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-18-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | rows = 40 7 | count = 0 8 | 9 | current_row = input.chars.map do |char| 10 | if char == '^' 11 | 1 12 | else 13 | count += 1 14 | 0 15 | end 16 | end 17 | 18 | row_length = current_row.length 19 | 20 | (rows - 1).times do 21 | prev_row = current_row 22 | current_row = [] 23 | 24 | row_length.times do |col| 25 | left = col > 0 ? prev_row[col - 1] : 0 26 | center = prev_row[col] 27 | right = prev_row[col + 1] || 0 28 | 29 | tile = (left ^ center) ^ (right ^ center) 30 | 31 | count += 1 if tile == 0 32 | current_row << tile 33 | end 34 | end 35 | 36 | puts count 37 | -------------------------------------------------------------------------------- /2016/day-18/day-18-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-18-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | rows = 400_000 7 | count = 0 8 | 9 | current_row = input.chars.map do |char| 10 | if char == '^' 11 | 1 12 | else 13 | count += 1 14 | 0 15 | end 16 | end 17 | 18 | row_length = current_row.length 19 | 20 | (rows - 1).times do 21 | prev_row = current_row 22 | current_row = [] 23 | 24 | row_length.times do |col| 25 | left = col > 0 ? prev_row[col - 1] : 0 26 | center = prev_row[col] 27 | right = prev_row[col + 1] || 0 28 | 29 | tile = left ^ center ^ right ^ center 30 | 31 | count += 1 if tile == 0 32 | current_row << tile 33 | end 34 | end 35 | 36 | puts count 37 | -------------------------------------------------------------------------------- /2016/day-19/day-19-input.txt: -------------------------------------------------------------------------------- 1 | 3014387 -------------------------------------------------------------------------------- /2016/day-19/day-19-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-19-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | class Elf 7 | attr_reader :number 8 | attr_accessor :next_elf 9 | 10 | def initialize(number) 11 | @number = number 12 | end 13 | end 14 | 15 | elf_count = input.to_i 16 | 17 | first_elf = Elf.new(1) 18 | previous_elf = first_elf 19 | 20 | (elf_count - 1).times do |i| 21 | current_elf = Elf.new(i + 2) 22 | previous_elf.next_elf = current_elf 23 | previous_elf = current_elf 24 | end 25 | 26 | previous_elf.next_elf = first_elf 27 | 28 | current_elf = first_elf 29 | 30 | while elf_count != 1 do 31 | current_elf.next_elf = current_elf.next_elf.next_elf 32 | elf_count -= 1 33 | current_elf = current_elf.next_elf 34 | end 35 | 36 | puts current_elf.number 37 | -------------------------------------------------------------------------------- /2016/day-19/day-19-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-19-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | queue_one = [] 7 | queue_two = [] 8 | 9 | elf_count = input.to_i 10 | 11 | elf_count.times do |i| 12 | if i < elf_count / 2 13 | queue_one << i + 1 14 | else 15 | queue_two << i + 1 16 | end 17 | end 18 | 19 | while queue_one.size + queue_two.size > 1 20 | current_elf = queue_one.shift 21 | 22 | if queue_one.size == queue_two.size 23 | queue_one.pop 24 | else 25 | queue_two.shift 26 | end 27 | 28 | queue_two << current_elf 29 | queue_one << queue_two.shift 30 | end 31 | 32 | puts queue_one 33 | -------------------------------------------------------------------------------- /2016/day-20/day-20-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | ranges = input.split("\n").map do |range| 7 | range.split("-").map(&:to_i) 8 | end 9 | 10 | ranges.sort.each_cons(2) do |range_one, range_two| 11 | if range_one[1] < range_two[0] - 1 12 | puts range_one[1] + 1 13 | exit 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /2016/day-20/day-20-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | ranges = input.split("\n").map do |range| 7 | range.split("-").map(&:to_i) 8 | end 9 | 10 | ranges.sort! 11 | 12 | merged_ranges = [ranges.shift] 13 | 14 | ranges.each do |range| 15 | prev_range = merged_ranges.first 16 | 17 | if prev_range[1] >= range[0] - 1 18 | prev_range[1] = [prev_range[1], range[1]].max 19 | else 20 | merged_ranges.unshift(range) 21 | end 22 | end 23 | 24 | merged_ranges.sort! 25 | 26 | allowed_count = 0 27 | 28 | merged_ranges.each_cons(2) do |range_one, range_two| 29 | allowed_count += [range_two[0] - range_one[1] - 1, 0].max 30 | end 31 | 32 | puts allowed_count 33 | -------------------------------------------------------------------------------- /2016/day-22/day-22-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-22-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | lines = input.split("\n")[2..-1] 9 | 10 | Node = Struct.new(:x, :y, :size, :used, :avail) 11 | 12 | nodes = lines.map do |line| 13 | x, y, size, used, avail = line.match(/x(\d+)-y(\d+)\s*(\d+)T\s*(\d+)T\s*(\d+)T/)[1..-1].map(&:to_i) 14 | 15 | Node.new(x, y, size, used, avail) 16 | end 17 | 18 | pairs = [] 19 | 20 | nodes.select { |node| node.used > 0 }.each do |node_one| 21 | nodes. 22 | reject { |node| node_one == node }. 23 | select { |node| node_one.used <= node.avail }. 24 | each { |node_two| pairs << [node_one, node_two] } 25 | end 26 | 27 | puts pairs.count 28 | -------------------------------------------------------------------------------- /2016/day-23/day-23-input-part-2.txt: -------------------------------------------------------------------------------- 1 | cpy a b 2 | dec b 3 | cpy a d 4 | cpy 0 a 5 | cpy b c 6 | mul c d a 7 | cpy 0 d 8 | cpy 0 d 9 | cpy 0 d 10 | cpy 0 d 11 | dec b 12 | cpy b c 13 | cpy c d 14 | dec d 15 | inc c 16 | jnz d -2 17 | tgl c 18 | cpy -16 c 19 | jnz 1 c 20 | cpy 76 c 21 | jnz 80 d 22 | inc a 23 | inc d 24 | jnz d -2 25 | inc c 26 | jnz c -5 -------------------------------------------------------------------------------- /2016/day-23/day-23-input.txt: -------------------------------------------------------------------------------- 1 | cpy a b 2 | dec b 3 | cpy a d 4 | cpy 0 a 5 | cpy b c 6 | inc a 7 | dec c 8 | jnz c -2 9 | dec d 10 | jnz d -5 11 | dec b 12 | cpy b c 13 | cpy c d 14 | dec d 15 | inc c 16 | jnz d -2 17 | tgl c 18 | cpy -16 c 19 | jnz 1 c 20 | cpy 76 c 21 | jnz 80 d 22 | inc a 23 | inc d 24 | jnz d -2 25 | inc c 26 | jnz c -5 -------------------------------------------------------------------------------- /2016/day-25/day-25-input.txt: -------------------------------------------------------------------------------- 1 | cpy a d 2 | cpy 4 c 3 | cpy 633 b 4 | inc d 5 | dec b 6 | jnz b -2 7 | dec c 8 | jnz c -5 9 | cpy d a 10 | jnz 0 0 11 | cpy a b 12 | cpy 0 a 13 | cpy 2 c 14 | jnz b 2 15 | jnz 1 6 16 | dec b 17 | dec c 18 | jnz c -4 19 | inc a 20 | jnz 1 -7 21 | cpy 2 b 22 | jnz c 2 23 | jnz 1 4 24 | dec b 25 | dec c 26 | jnz 1 -4 27 | jnz 0 0 28 | out b 29 | jnz a -19 30 | jnz 1 -21 -------------------------------------------------------------------------------- /2017/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | digits = input.chars 7 | 8 | digits << digits.first 9 | 10 | puts digits.each_cons(2).to_a 11 | .select { |a, b| a == b } 12 | .map(&:first) 13 | .map(&:to_i) 14 | .inject(:+) 15 | -------------------------------------------------------------------------------- /2017/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | digits = input.chars 7 | 8 | length = digits.length 9 | 10 | puts digits.select 11 | .with_index { |d, idx| digits[(idx + length / 2) % length] == d } 12 | .map(&:to_i) 13 | .inject(:+) 14 | -------------------------------------------------------------------------------- /2017/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n") 7 | .map { |row| row.split(" ") .map(&:to_i).sort } 8 | .map { |row| row.last - row.first } 9 | .inject(:+) 10 | -------------------------------------------------------------------------------- /2017/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n") 7 | .map { |row| row.split(" ").map(&:to_i).sort } 8 | .map { |row| row.combination(2) } 9 | .map { |row| row.find { |a, b| b % a == 0 } } 10 | .map { |a, b| b / a } 11 | .inject(:+) 12 | -------------------------------------------------------------------------------- /2017/day-03/day-03-input.txt: -------------------------------------------------------------------------------- 1 | 277678 -------------------------------------------------------------------------------- /2017/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | target = input.to_i 7 | dimension = Math.sqrt(target).ceil 8 | 9 | grid = Array.new(dimension) { Array.new(dimension) } 10 | start = dimension / 2 11 | x = y = start 12 | 13 | dirs = [:right, :up, :left, :down] 14 | dir = dirs[0] 15 | 16 | def move(x, y, dir) 17 | case dir 18 | when :right 19 | x += 1 20 | when :up 21 | y -= 1 22 | when :left 23 | x -= 1 24 | when :down 25 | y += 1 26 | end 27 | 28 | [x, y] 29 | end 30 | 31 | (target - 1).times do |i| 32 | grid[y][x] = i + 1 33 | 34 | next_dir = dirs[(dirs.index(dir) + 1) % dirs.length] 35 | x1, y1 = move(x, y, next_dir) 36 | dir = next_dir if grid[y1][x1].nil? 37 | 38 | x, y = move(x, y, dir) 39 | end 40 | 41 | puts (x - start).abs + (y - start).abs 42 | -------------------------------------------------------------------------------- /2017/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n").count { |pw| 7 | pw.split(" ").uniq.length == pw.split(" ").length 8 | } 9 | -------------------------------------------------------------------------------- /2017/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n").count { |pw| 7 | words = pw.split(" ").map { |word| word.chars.sort.join } 8 | 9 | words.uniq.length == words.length 10 | } 11 | -------------------------------------------------------------------------------- /2017/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | offsets = input.split("\n").map(&:to_i) 7 | 8 | position = 0 9 | jumps = 0 10 | 11 | while position < offsets.length 12 | move = offsets[position] 13 | offsets[position] += 1 14 | position += move 15 | 16 | jumps += 1 17 | end 18 | 19 | puts jumps 20 | -------------------------------------------------------------------------------- /2017/day-05/day-05-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | offsets = input.split("\n").map(&:to_i) 7 | 8 | position = 0 9 | jumps = 0 10 | 11 | while position < offsets.length 12 | move = offsets[position] 13 | 14 | if offsets[position] >= 3 15 | offsets[position] -= 1 16 | else 17 | offsets[position] += 1 18 | end 19 | 20 | position += move 21 | 22 | jumps += 1 23 | end 24 | 25 | puts jumps 26 | -------------------------------------------------------------------------------- /2017/day-06/day-06-input.txt: -------------------------------------------------------------------------------- 1 | 11 11 13 7 0 15 5 5 4 4 1 1 7 1 15 11 -------------------------------------------------------------------------------- /2017/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes Part 2 4 | 5 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | banks = input.split(" ").map(&:to_i) 9 | 10 | configurations = {} 11 | 12 | steps = 0 13 | 14 | until configurations[banks] 15 | configurations[banks] = steps 16 | 17 | idx = banks.index(banks.max) 18 | 19 | blocks = banks[idx] 20 | banks[idx] = 0 21 | 22 | blocks.times do |i| 23 | banks[(idx + i + 1) % banks.length] += 1 24 | end 25 | 26 | steps += 1 27 | end 28 | 29 | # Part 1 30 | puts steps 31 | 32 | # Part 2 33 | puts steps - configurations[banks] -------------------------------------------------------------------------------- /2017/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Identical to Part 1 4 | 5 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | banks = input.split(" ").map(&:to_i) 9 | 10 | configurations = {} 11 | 12 | steps = 0 13 | 14 | until configurations[banks] 15 | configurations[banks] = steps 16 | 17 | idx = banks.index(banks.max) 18 | 19 | blocks = banks[idx] 20 | banks[idx] = 0 21 | 22 | blocks.times do |i| 23 | banks[(idx + i + 1) % banks.length] += 1 24 | end 25 | 26 | steps += 1 27 | end 28 | 29 | # Part 1 30 | puts steps 31 | 32 | # Part 2 33 | puts steps - configurations[banks] -------------------------------------------------------------------------------- /2017/day-07/day-07-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | programs = input.split("\n") 7 | 8 | parents = [] 9 | children = [] 10 | 11 | programs.each do |disc| 12 | next unless disc.include?("->") 13 | 14 | parents << disc.split(" ").first 15 | children += disc.split("->").last.gsub!(",", "").split(" ") 16 | end 17 | 18 | puts parents - children 19 | -------------------------------------------------------------------------------- /2017/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes Part 2 4 | 5 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | instructions = input.split("\n") 9 | 10 | registers = Hash.new(0) 11 | max_value = 0 12 | 13 | instructions.each do |instruction| 14 | reg, cmd, amount, _, con_reg, con, con_val = 15 | instruction.split(" ") 16 | 17 | amount = amount.to_i 18 | con_val = con_val.to_i 19 | 20 | if registers[con_reg].send(con, con_val) 21 | if cmd == 'inc' 22 | registers[reg] += amount 23 | else 24 | registers[reg] -= amount 25 | end 26 | end 27 | 28 | max_value = [registers[reg], max_value].max 29 | end 30 | 31 | puts registers.values.max 32 | puts max_value 33 | -------------------------------------------------------------------------------- /2017/day-08/day-08-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Identical to Part 1 4 | 5 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | instructions = input.split("\n") 9 | 10 | registers = Hash.new(0) 11 | max_value = 0 12 | 13 | instructions.each do |instruction| 14 | reg, cmd, amount, _, con_reg, con, con_val = 15 | instruction.split(" ") 16 | 17 | amount = amount.to_i 18 | con_val = con_val.to_i 19 | 20 | if registers[con_reg].send(con, con_val) 21 | if cmd == 'inc' 22 | registers[reg] += amount 23 | else 24 | registers[reg] -= amount 25 | end 26 | end 27 | 28 | max_value = [registers[reg], max_value].max 29 | end 30 | 31 | puts registers.values.max 32 | puts max_value 33 | -------------------------------------------------------------------------------- /2017/day-09/day-09-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes Part 2 4 | 5 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | stream = input.chars 9 | 10 | clean_stream = [] 11 | garbage_mode = false 12 | 13 | garbage_count = 0 14 | 15 | while stream.any? 16 | char = stream.shift 17 | 18 | if char == '!' 19 | stream.shift 20 | elsif char == '<' 21 | garbage_mode = true 22 | elsif garbage_mode 23 | if char == '>' 24 | garbage_mode = false 25 | else 26 | garbage_count += 1 27 | end 28 | elsif char == '{' || char == '}' 29 | clean_stream << char 30 | end 31 | end 32 | 33 | puts garbage_count 34 | 35 | score = 0 36 | level = 0 37 | 38 | while clean_stream.any? 39 | if clean_stream.shift == '{' 40 | level += 1 41 | score += level 42 | else 43 | level -= 1 44 | end 45 | end 46 | 47 | puts score 48 | -------------------------------------------------------------------------------- /2017/day-09/day-09-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Identical to Part 1 4 | 5 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | stream = input.chars 9 | 10 | clean_stream = [] 11 | garbage_mode = false 12 | 13 | garbage_count = 0 14 | 15 | while stream.any? 16 | char = stream.shift 17 | 18 | if char == '!' 19 | stream.shift 20 | elsif char == '<' 21 | garbage_mode = true 22 | elsif garbage_mode 23 | if char == '>' 24 | garbage_mode = false 25 | else 26 | garbage_count += 1 27 | end 28 | elsif char == '{' || char == '}' 29 | clean_stream << char 30 | end 31 | end 32 | 33 | puts garbage_count 34 | 35 | score = 0 36 | level = 0 37 | 38 | while clean_stream.any? 39 | if clean_stream.shift == '{' 40 | level += 1 41 | score += level 42 | else 43 | level -= 1 44 | end 45 | end 46 | 47 | puts score 48 | -------------------------------------------------------------------------------- /2017/day-10/day-10-input.txt: -------------------------------------------------------------------------------- 1 | 120,93,0,90,5,80,129,74,1,165,204,255,254,2,50,113 -------------------------------------------------------------------------------- /2017/day-10/day-10-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lengths = input.split(",").map(&:to_i) 7 | 8 | size = 256 9 | list = (0..(size - 1)).to_a 10 | 11 | idx = 0 12 | skip = 0 13 | 14 | lengths.each do |length| 15 | list.rotate!(idx) 16 | list[0, length] = list[0, length].reverse 17 | list.rotate!(-idx) 18 | 19 | idx = (idx + length + skip) % size 20 | skip += 1 21 | end 22 | 23 | puts list[0] * list[1] 24 | -------------------------------------------------------------------------------- /2017/day-10/day-10-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lengths = input.bytes 7 | lengths.concat [17, 31, 73, 47, 23] 8 | 9 | size = 256 10 | list = (0..(size - 1)).to_a 11 | 12 | idx = 0 13 | skip = 0 14 | 15 | 64.times do 16 | lengths.each do |length| 17 | list.rotate!(idx) 18 | list[0, length] = list[0, length].reverse 19 | list.rotate!(-idx) 20 | 21 | idx = (idx + length + skip) % size 22 | skip += 1 23 | end 24 | end 25 | 26 | puts list 27 | .each_slice(16) 28 | .map { |l| l.inject(:^).to_s(16).rjust(2, '0') } 29 | .join 30 | -------------------------------------------------------------------------------- /2017/day-11/day-11-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | x = 0 7 | y = 0 8 | 9 | input.split(",").each do |dir| 10 | case dir 11 | when "ne" 12 | x += 1 13 | when "sw" 14 | x -= 1 15 | when "se" 16 | x += 1 17 | y += 1 18 | when "nw" 19 | x -= 1 20 | y -= 1 21 | when "s" 22 | y += 1 23 | when "n" 24 | y -= 1 25 | end 26 | end 27 | 28 | steps = 0 29 | 30 | puts [x.abs, y.abs, (x - y).abs].max 31 | -------------------------------------------------------------------------------- /2017/day-11/day-11-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | x = 0 7 | y = 0 8 | 9 | max = 0 10 | 11 | input.split(",").each do |dir| 12 | case dir 13 | when "ne" 14 | x += 1 15 | when "sw" 16 | x -= 1 17 | when "se" 18 | x += 1 19 | y += 1 20 | when "nw" 21 | x -= 1 22 | y -= 1 23 | when "s" 24 | y += 1 25 | when "n" 26 | y -= 1 27 | end 28 | 29 | max = [x.abs, y.abs, (x - y).abs, max].max 30 | end 31 | 32 | puts max 33 | -------------------------------------------------------------------------------- /2017/day-12/day-12-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | programs = Hash.new { |h,k| h[k] = [] } 9 | 10 | input.split("\n").each do |line| 11 | from, *to = line.split(/<->|,/).map(&:to_i) 12 | programs[from].concat to 13 | end 14 | 15 | queue = [0] 16 | group = Set.new 17 | 18 | while queue.any? 19 | pg = queue.pop 20 | group.add(pg) 21 | 22 | queue += programs[pg].reject { |pro| group.include?(pro) } 23 | end 24 | 25 | puts group.size 26 | -------------------------------------------------------------------------------- /2017/day-12/day-12-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | programs = Hash.new { |h,k| h[k] = [] } 9 | 10 | input.split("\n").each do |line| 11 | from, *to = line.split(/<->|,/).map(&:to_i) 12 | programs[from].concat to 13 | end 14 | 15 | groups = 0 16 | 17 | while programs.any? 18 | group = Set.new 19 | 20 | queue = [programs.keys.first] 21 | 22 | while queue.any? 23 | pg = queue.pop 24 | group.add(pg) 25 | 26 | queue += programs[pg].reject { |pro| group.include?(pro) } 27 | end 28 | 29 | group.each do |pg| 30 | programs.delete(pg) 31 | end 32 | 33 | groups += 1 34 | end 35 | 36 | puts groups 37 | -------------------------------------------------------------------------------- /2017/day-13/day-13-input.txt: -------------------------------------------------------------------------------- 1 | 0: 3 2 | 1: 2 3 | 2: 4 4 | 4: 8 5 | 6: 5 6 | 8: 6 7 | 10: 6 8 | 12: 4 9 | 14: 6 10 | 16: 6 11 | 18: 9 12 | 20: 8 13 | 22: 8 14 | 24: 8 15 | 26: 8 16 | 28: 10 17 | 30: 8 18 | 32: 12 19 | 34: 10 20 | 36: 14 21 | 38: 12 22 | 40: 12 23 | 42: 12 24 | 44: 12 25 | 46: 12 26 | 48: 12 27 | 50: 14 28 | 52: 12 29 | 54: 14 30 | 56: 12 31 | 58: 12 32 | 60: 14 33 | 62: 18 34 | 64: 14 35 | 68: 14 36 | 70: 14 37 | 72: 14 38 | 74: 14 39 | 78: 14 40 | 80: 20 41 | 82: 14 42 | 84: 14 43 | 90: 17 -------------------------------------------------------------------------------- /2017/day-13/day-13-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-13-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | layers = {} 7 | 8 | input.split("\n").each do |layer| 9 | depth, range = layer.split(':').map(&:to_i) 10 | layers[depth] = range 11 | end 12 | 13 | puts layers 14 | .map { |i, range| range * i if i % ((range - 1) * 2) == 0 } 15 | .compact 16 | .inject(:+) 17 | -------------------------------------------------------------------------------- /2017/day-13/day-13-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-13-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | layers = {} 7 | 8 | input.split("\n").each do |layer| 9 | depth, range = layer.split(':').map(&:to_i) 10 | layers[depth] = range 11 | end 12 | 13 | puts (0..Float::INFINITY).find { |delay| 14 | layers.none? do |pos, range| 15 | (pos + delay) % ((range - 1) * 2) == 0 16 | end 17 | } 18 | -------------------------------------------------------------------------------- /2017/day-14/day-14-input.txt: -------------------------------------------------------------------------------- 1 | ffayrhll -------------------------------------------------------------------------------- /2017/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | def knot_hash(input) 7 | lengths = input.bytes 8 | lengths.concat [17, 31, 73, 47, 23] 9 | 10 | size = 256 11 | list = (0..(size - 1)).to_a 12 | 13 | idx = 0 14 | skip = 0 15 | 16 | 64.times do 17 | lengths.each do |length| 18 | list.rotate!(idx) 19 | list[0, length] = list[0, length].reverse 20 | list.rotate!(-idx) 21 | 22 | idx = (idx + length + skip) % size 23 | skip += 1 24 | end 25 | end 26 | 27 | list 28 | .each_slice(16) 29 | .map { |l| l.inject(:^).to_s(16).rjust(2, '0') } 30 | .join 31 | end 32 | 33 | rows = 128.times.map do |i| 34 | knot_hash("#{input}-#{i}") 35 | .to_i(16).to_s(2) 36 | .rjust(128, '0').split("") 37 | end 38 | 39 | puts rows.flatten.select{ |c| c == '1'}.length 40 | -------------------------------------------------------------------------------- /2017/day-15/day-15-input.txt: -------------------------------------------------------------------------------- 1 | Generator A starts with 873 2 | Generator B starts with 583 -------------------------------------------------------------------------------- /2017/day-15/day-15-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-15-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | a, b = input.scan(/\d+$/).map(&:to_i) 7 | 8 | count = 0 9 | mask = 2 ** 16 - 1 10 | 11 | 40_000_000.times do 12 | a = (a * 16807) % 2147483647 13 | b = (b * 48271) % 2147483647 14 | 15 | count += 1 if (a ^ b) & mask == 0 16 | end 17 | 18 | puts count 19 | -------------------------------------------------------------------------------- /2017/day-15/day-15-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-15-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | a, b = input.scan(/\d+$/).map(&:to_i) 7 | 8 | count = 0 9 | mask = 2 ** 16 - 1 10 | 11 | 5_000_000.times do 12 | loop do 13 | a = (a * 16807) % 2147483647 14 | break if a % 4 == 0 15 | end 16 | 17 | loop do 18 | b = (b * 48271) % 2147483647 19 | break if b % 8 == 0 20 | end 21 | 22 | count += 1 if (a ^ b) & mask == 0 23 | end 24 | 25 | puts count 26 | -------------------------------------------------------------------------------- /2017/day-16/day-16-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-16-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | pro = ('a'..'p').to_a 7 | 8 | input.split(",").each do |instr| 9 | case instr[0] 10 | when 's' 11 | pro.rotate!(-instr[1..-1].to_i) 12 | when 'x' 13 | a, b = instr.scan(/\d+/).map(&:to_i) 14 | pro[a], pro[b] = pro[b], pro[a] 15 | when 'p' 16 | a, b = instr[1..-1].scan(/\w/).map { |p| pro.index(p) } 17 | pro[a], pro[b] = pro[b], pro[a] 18 | end 19 | end 20 | 21 | puts pro.join 22 | -------------------------------------------------------------------------------- /2017/day-16/day-16-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-16-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | pro = ('a'..'p').to_a 7 | 8 | visited = {} 9 | 10 | dance = 0 11 | 12 | until visited[pro.join] 13 | visited[pro.join] = dance 14 | dance += 1 15 | 16 | input.split(",").each do |instr| 17 | case instr[0] 18 | when 's' 19 | pro.rotate!(-instr[1..-1].to_i) 20 | when 'x' 21 | a, b = instr.scan(/\d+/).map(&:to_i) 22 | pro[a], pro[b] = pro[b], pro[a] 23 | when 'p' 24 | a, b = instr[1..-1].scan(/\w/).map { |p| pro.index(p) } 25 | pro[a], pro[b] = pro[b], pro[a] 26 | end 27 | end 28 | end 29 | 30 | puts visited.to_a.map(&:reverse) 31 | .sort.map(&:last) 32 | .fetch(1_000_000_000 % visited.size) 33 | -------------------------------------------------------------------------------- /2017/day-17/day-17-input.txt: -------------------------------------------------------------------------------- 1 | 376 -------------------------------------------------------------------------------- /2017/day-17/day-17-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-17-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | steps = input.to_i 7 | 8 | buffer = [0] 9 | pos = 0 10 | 11 | 2017.times do |i| 12 | pos = (pos + steps) % buffer.size + 1 13 | buffer.insert(pos, i + 1) 14 | end 15 | 16 | puts buffer[pos + 1] 17 | -------------------------------------------------------------------------------- /2017/day-17/day-17-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-17-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | steps = input.to_i 7 | pos = 0 8 | 9 | size = 1 10 | val = nil 11 | 12 | 50000000.times do |i| 13 | pos = (pos + steps) % size + 1 14 | 15 | val = i + 1 if pos == 1 16 | size += 1 17 | end 18 | 19 | puts val 20 | -------------------------------------------------------------------------------- /2017/day-18/day-18-input.txt: -------------------------------------------------------------------------------- 1 | set i 31 2 | set a 1 3 | mul p 17 4 | jgz p p 5 | mul a 2 6 | add i -1 7 | jgz i -2 8 | add a -1 9 | set i 127 10 | set p 680 11 | mul p 8505 12 | mod p a 13 | mul p 129749 14 | add p 12345 15 | mod p a 16 | set b p 17 | mod b 10000 18 | snd b 19 | add i -1 20 | jgz i -9 21 | jgz a 3 22 | rcv b 23 | jgz b -1 24 | set f 0 25 | set i 126 26 | rcv a 27 | rcv b 28 | set p a 29 | mul p -1 30 | add p b 31 | jgz p 4 32 | snd a 33 | set a b 34 | jgz 1 3 35 | snd b 36 | set f 1 37 | add i -1 38 | jgz i -11 39 | snd a 40 | jgz f -16 41 | jgz a -19 -------------------------------------------------------------------------------- /2017/day-18/day-18-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-18-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | insts = input.split("\n") 7 | 8 | r = Hash.new(0) 9 | freq = 0 10 | idx = 0 11 | 12 | until idx >= insts.length 13 | cmd, x, y = insts[idx].split(" ") 14 | 15 | y = y =~ /\d/ ? y.to_i : r[y] 16 | 17 | case cmd 18 | when 'snd' 19 | freq = r[x] 20 | when 'set' 21 | r[x] = y 22 | when 'add' 23 | r[x] += y 24 | when 'mul' 25 | r[x] *= y 26 | when 'mod' 27 | r[x] %= y 28 | when 'rcv' 29 | break if r[x] != 0 30 | when 'jgz' 31 | idx += (y - 1) if r[x] > 0 32 | end 33 | 34 | idx += 1 35 | end 36 | 37 | puts freq 38 | -------------------------------------------------------------------------------- /2017/day-20/day-20-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | class Particle 7 | attr_accessor :p, :v, :a, :i 8 | 9 | def initialize(pva, i) 10 | @i = i 11 | @p, @v, @a = *pva 12 | end 13 | 14 | def tick 15 | @v = v.zip(a).map { |v, a| v + a } 16 | @p = p.zip(v).map { |p, v| p + v } 17 | end 18 | 19 | def distance 20 | p.map(&:abs).inject(:+) 21 | end 22 | end 23 | 24 | particles = input.split("\n").map.with_index do |part, i| 25 | pva = part.split('>,').map do |vec| 26 | vec.scan(/-*\d+/).to_a.map(&:to_i) 27 | end 28 | 29 | Particle.new(pva, i) 30 | end 31 | 32 | closest = [] 33 | 34 | while true 35 | particles.each(&:tick) 36 | 37 | min = particles.map(&:distance).min 38 | closest << particles.find { |p| p.distance == min }.i 39 | 40 | break if closest.size > 300 && closest[-300..-1].uniq.size == 1 41 | end 42 | 43 | puts closest.last 44 | -------------------------------------------------------------------------------- /2017/day-20/day-20-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | class Particle 7 | attr_accessor :p, :v, :a, :i 8 | 9 | def initialize(pva, i) 10 | @i = i 11 | @p, @v, @a = *pva 12 | end 13 | 14 | def tick 15 | @v = v.zip(a).map { |v, a| v + a } 16 | @p = p.zip(v).map { |p, v| p + v } 17 | end 18 | end 19 | 20 | particles = input.split("\n").map.with_index do |part, i| 21 | pva = part.split('>,').map do |vec| 22 | vec.scan(/-*\d+/).to_a.map(&:to_i) 23 | end 24 | 25 | Particle.new(pva, i) 26 | end 27 | 28 | counts = [] 29 | 30 | while true 31 | particles.each(&:tick) 32 | 33 | particles.product(particles).each do |p, o| 34 | next if o == p || p.p != o.p 35 | particles.delete(p) 36 | particles.delete(o) 37 | end 38 | 39 | puts particles.size 40 | counts << particles.size 41 | 42 | break if counts.size > 9 && counts[-9..-1].uniq.size == 1 43 | end 44 | -------------------------------------------------------------------------------- /2017/day-22/day-22-input.txt: -------------------------------------------------------------------------------- 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 | #......####.#.##.#.###.## -------------------------------------------------------------------------------- /2017/day-23/day-23-input.txt: -------------------------------------------------------------------------------- 1 | set b 99 2 | set c b 3 | jnz a 2 4 | jnz 1 5 5 | mul b 100 6 | sub b -100000 7 | set c b 8 | sub c -17000 9 | set f 1 10 | set d 2 11 | set e 2 12 | set g d 13 | mul g e 14 | sub g b 15 | jnz g 2 16 | set f 0 17 | sub e -1 18 | set g e 19 | sub g b 20 | jnz g -8 21 | sub d -1 22 | set g d 23 | sub g b 24 | jnz g -13 25 | jnz f 2 26 | sub h -1 27 | set g b 28 | sub g c 29 | jnz g 2 30 | jnz 1 3 31 | sub b -17 32 | jnz 1 -23 -------------------------------------------------------------------------------- /2017/day-23/day-23-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-23-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | reg = Hash.new(0) 7 | 8 | cmds = input.split("\n") 9 | idx = 0 10 | count = 0 11 | 12 | until idx >= cmds.length 13 | a, b, c = cmds[idx].split(" ") 14 | 15 | if c =~ /\d/ 16 | c = c.to_i 17 | else 18 | c = reg[c] 19 | end 20 | 21 | case a 22 | when 'set' 23 | reg[b] = c 24 | when 'sub' 25 | reg[b] -= c 26 | when 'mul' 27 | reg[b] *= c 28 | count += 1 29 | when 'jnz' 30 | b = b =~ /\d/ ? b.to_i : reg[b] 31 | idx += (c - 1) if b != 0 32 | end 33 | 34 | idx += 1 35 | end 36 | 37 | puts count -------------------------------------------------------------------------------- /2017/day-23/day-23-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Count composite (non-prime) numbers from b to c 4 | 5 | b = 109900 6 | c = b + 17000 7 | 8 | puts (b..c).step(17).count { |b| 9 | (2..(Math.sqrt(b))).any? { |e| b % e == 0 } 10 | } 11 | -------------------------------------------------------------------------------- /2017/day-24/day-24-input.txt: -------------------------------------------------------------------------------- 1 | 42/37 2 | 28/28 3 | 29/25 4 | 45/8 5 | 35/23 6 | 49/20 7 | 44/4 8 | 15/33 9 | 14/19 10 | 31/44 11 | 39/14 12 | 25/17 13 | 34/34 14 | 38/42 15 | 8/42 16 | 15/28 17 | 0/7 18 | 49/12 19 | 18/36 20 | 45/45 21 | 28/7 22 | 30/43 23 | 23/41 24 | 0/35 25 | 18/9 26 | 3/31 27 | 20/31 28 | 10/40 29 | 0/22 30 | 1/23 31 | 20/47 32 | 38/36 33 | 15/8 34 | 34/32 35 | 30/30 36 | 30/44 37 | 19/28 38 | 46/15 39 | 34/50 40 | 40/20 41 | 27/39 42 | 3/14 43 | 43/45 44 | 50/42 45 | 1/33 46 | 6/39 47 | 46/44 48 | 22/35 49 | 15/20 50 | 43/31 51 | 23/23 52 | 19/27 53 | 47/15 54 | 43/43 55 | 25/36 56 | 26/38 57 | 1/10 -------------------------------------------------------------------------------- /2017/day-24/day-24-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-24-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | comps = input.split("\n") 7 | .map { |comp| comp.split('/').map(&:to_i) } 8 | 9 | max = 0 10 | 11 | queue = comps.select { |comp| comp.include?(0) } 12 | .map { |comp| 13 | remaining = comps.reject { |c| c == comp } 14 | target = comp[0] 15 | target = comp[1] if target == 0 16 | sum = comp.inject(:+) 17 | 18 | [remaining, target, sum] 19 | } 20 | 21 | while queue.any? 22 | comps, target, sum = queue.pop 23 | 24 | max = [sum, max].max 25 | 26 | comps.select { |comp| comp.include?(target) }.each do |comp| 27 | remaining = comps.reject { |c| c == comp } 28 | new_target = comp[0] 29 | new_target = comp[1] if new_target == target 30 | new_sum = sum + comp.inject(:+) 31 | 32 | queue << [remaining, new_target, new_sum] 33 | end 34 | end 35 | 36 | puts max 37 | -------------------------------------------------------------------------------- /2018/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n").map(&:to_i).inject(:+) 7 | -------------------------------------------------------------------------------- /2018/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | changes = input.split("\n") 9 | 10 | sum = 0 11 | sums = Set.new 12 | 13 | while true 14 | changes.each do |change| 15 | sum += change.to_i 16 | 17 | if sums.include?(sum) 18 | puts sum 19 | exit 20 | end 21 | 22 | sums.add(sum) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /2018/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | twos = 0 7 | threes = 0 8 | 9 | input.split("\n").each do |row| 10 | counts = Hash.new(0) 11 | 12 | row.chars.each do |char| 13 | counts[char] += 1 14 | end 15 | 16 | counts = counts.invert 17 | 18 | twos += 1 if counts[2] 19 | threes += 1 if counts[3] 20 | end 21 | 22 | puts twos * threes 23 | -------------------------------------------------------------------------------- /2018/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | boxes = input.split("\n") 7 | 8 | boxes.first.length.times do |column| 9 | counts = Hash.new(0) 10 | 11 | boxes.map do |box| 12 | id = box[0...column] + box[(column + 1)..-1] 13 | counts[id] += 1 14 | end 15 | 16 | counts = counts.invert 17 | 18 | if counts[2] 19 | puts counts[2] 20 | break 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /2018/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | grid = Array.new(1000) { Array.new(1000, 0) } 7 | 8 | claims = input.split("\n") 9 | 10 | claims.each do |claim| 11 | ord, dim = claim.split("@").last.split(":") 12 | x, y = ord.split(",").map(&:to_i) 13 | w, h = dim.split("x").map(&:to_i) 14 | 15 | w.times do |x1| 16 | h.times do |y1| 17 | grid[x + x1][y + y1] += 1 18 | end 19 | end 20 | end 21 | 22 | puts grid.flatten.select { |cell| cell > 1 }.count 23 | -------------------------------------------------------------------------------- /2018/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | grid = Array.new(1000) { Array.new(1000) { Set.new } } 9 | candidates = Set.new 10 | 11 | claims = input.split("\n") 12 | 13 | claims.each do |claim| 14 | id, claim = claim.split("@") 15 | ord, dim = claim.split(":") 16 | x, y = ord.split(",").map(&:to_i) 17 | w, h = dim.split("x").map(&:to_i) 18 | id = id[1..-1].to_i 19 | 20 | candidates.add id 21 | 22 | w.times do |x1| 23 | h.times do |y1| 24 | cell = grid[x+x1][y+y1] 25 | 26 | if cell.any? 27 | candidates.delete id 28 | 29 | cell.each do |c| 30 | candidates.delete c 31 | end 32 | end 33 | 34 | cell.add id 35 | end 36 | end 37 | end 38 | 39 | puts candidates.to_a 40 | -------------------------------------------------------------------------------- /2018/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | guard_logs = input.split("\n").sort. 7 | slice_before { |l| l.include?("begin") } 8 | 9 | guards = Hash.new { |h, k| h[k] = [] } 10 | 11 | guard_logs.each do |logs| 12 | id = logs.shift.scan(/#(\d*)/)[0][0].to_i 13 | 14 | logs.each_slice(2) do |asleep, wake| 15 | h, m = asleep.scan(/(\d*):(\d*)/)[0] 16 | start = h.to_i * 60 + m.to_i 17 | 18 | h, m = wake.scan(/(\d*):(\d*)/)[0] 19 | stop = h.to_i * 60 + m.to_i 20 | 21 | guards[id] << (start..stop) 22 | end 23 | end 24 | 25 | id, _ = guards.max_by do |id, sleeps| 26 | sleeps.map(&:size).inject(:+) 27 | end 28 | 29 | minute_counts = Hash.new(0) 30 | 31 | guards[id].each do |range| 32 | range.min...range.max do |i| 33 | minute_counts[i] += 1 34 | end 35 | end 36 | 37 | minute, _ = minute_counts.max_by { |_minute, count| count } 38 | 39 | puts id * (minute - 1) 40 | -------------------------------------------------------------------------------- /2018/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | loop do 7 | prev_length = input.length 8 | 9 | input.gsub!(/([A-z])\1+/i) do |match| 10 | chr = match[0] 11 | pattern = chr.downcase + chr.upcase 12 | 13 | match 14 | .gsub(pattern, "") 15 | .gsub(pattern.reverse, "") 16 | end 17 | 18 | break if input.length == prev_length 19 | end 20 | 21 | puts input.length -------------------------------------------------------------------------------- /2018/day-05/day-05-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | shortest = nil 7 | 8 | ('a'..'z').each do |char| 9 | test = input.gsub(/#{char}/i, "") 10 | 11 | loop do 12 | prev_length = test.length 13 | 14 | test.gsub!(/([A-z])\1+/i) do |match| 15 | chr = match[0] 16 | pattern = chr.downcase + chr.upcase 17 | 18 | match 19 | .gsub(pattern, "") 20 | .gsub(pattern.reverse, "") 21 | end 22 | 23 | break if test.length == prev_length 24 | end 25 | 26 | 27 | if shortest.nil? || test.length < shortest 28 | shortest = test.length 29 | puts char 30 | puts shortest 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /2018/day-06/day-06-input.txt: -------------------------------------------------------------------------------- 1 | 227, 133 2 | 140, 168 3 | 99, 112 4 | 318, 95 5 | 219, 266 6 | 134, 144 7 | 306, 301 8 | 189, 188 9 | 58, 334 10 | 337, 117 11 | 255, 73 12 | 245, 144 13 | 102, 257 14 | 255, 353 15 | 303, 216 16 | 141, 167 17 | 40, 321 18 | 201, 50 19 | 60, 188 20 | 132, 74 21 | 125, 199 22 | 176, 307 23 | 204, 218 24 | 338, 323 25 | 276, 278 26 | 292, 229 27 | 109, 228 28 | 85, 305 29 | 86, 343 30 | 97, 254 31 | 182, 151 32 | 110, 292 33 | 285, 124 34 | 43, 223 35 | 153, 188 36 | 285, 136 37 | 334, 203 38 | 84, 243 39 | 92, 185 40 | 330, 223 41 | 259, 275 42 | 106, 199 43 | 183, 205 44 | 188, 212 45 | 231, 150 46 | 158, 95 47 | 174, 212 48 | 279, 97 49 | 172, 131 50 | 247, 320 -------------------------------------------------------------------------------- /2018/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | ords = input.split("\n").map do |ord| 7 | x, y = ord.split(",").map(&:to_i) 8 | end 9 | 10 | rows = ords.map(&:first).max + 1 11 | cols = ords.map(&:last).max + 1 12 | 13 | count = 0 14 | 15 | rows.times do |x| 16 | cols.times do |y| 17 | sum = ords.map.inject(0) do |sum, (x1, y1)| 18 | sum + (x - x1).abs + (y - y1).abs 19 | end 20 | 21 | count += 1 if sum < 10000 22 | end 23 | end 24 | 25 | puts count 26 | -------------------------------------------------------------------------------- /2018/day-07/day-07-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | rules = input.split("\n") 7 | 8 | steps = Hash.new { |h, k| h[k] = Array.new } 9 | 10 | rules.each do |rule| 11 | req, step = rule.scan(/\s(\w)\s/).map(&:first) 12 | 13 | steps[step] << req 14 | end 15 | 16 | todo = ("A"..(steps.keys.max)).to_a 17 | 18 | done = [] 19 | 20 | while todo.any? 21 | todo.each do |step| 22 | next if steps[step].any? 23 | 24 | todo.delete(step) 25 | done << step 26 | 27 | steps.each do |_, reqs| 28 | reqs.delete(step) 29 | end 30 | 31 | break 32 | end 33 | end 34 | 35 | puts done.join 36 | -------------------------------------------------------------------------------- /2018/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | numbers = input.split.map(&:to_i) 7 | 8 | def sum(numbers) 9 | child_nodes = numbers.shift 10 | meta_entries = numbers.shift 11 | 12 | sum = 0 13 | 14 | child_nodes.times do 15 | sum += sum(numbers) 16 | end 17 | 18 | meta_entries.times do 19 | sum += numbers.shift 20 | end 21 | 22 | sum 23 | end 24 | 25 | puts sum(numbers) 26 | -------------------------------------------------------------------------------- /2018/day-08/day-08-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | numbers = input.split.map(&:to_i) 7 | 8 | def sum(numbers) 9 | child_nodes = numbers.shift 10 | meta_entries = numbers.shift 11 | 12 | child_sums = child_nodes.times.map do 13 | sum(numbers) 14 | end 15 | 16 | entries = meta_entries.times.map do 17 | numbers.shift 18 | end 19 | 20 | if child_nodes == 0 21 | entries.inject(:+) 22 | else 23 | entries.map { |idx| child_sums[idx-1] } 24 | .compact.inject(:+) 25 | end 26 | end 27 | 28 | puts sum(numbers) 29 | -------------------------------------------------------------------------------- /2018/day-09/day-09-input.txt: -------------------------------------------------------------------------------- 1 | 455 players; last marble is worth 71223 points -------------------------------------------------------------------------------- /2018/day-11/day-11-input.txt: -------------------------------------------------------------------------------- 1 | 3613 -------------------------------------------------------------------------------- /2018/day-11/day-11-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | serial = input.to_i 7 | 8 | def power(x, y, serial) 9 | id = x + 10 10 | power = id * y 11 | power += serial 12 | power *= id 13 | hundredth = (power / 100) % 10 14 | hundredth - 5 15 | end 16 | 17 | grid = Array.new(300) { Array.new(300, 0) } 18 | 19 | 300.times do |x| 20 | 300.times do |y| 21 | grid[x][y] = power(x, y, serial) 22 | end 23 | end 24 | 25 | max = max_x = max_y = nil 26 | 27 | 297.times do |x| 28 | 297.times do |y| 29 | sum = 0 30 | 31 | 3.times do |x1| 32 | 3.times do |y1| 33 | sum += grid[x+x1][y+y1] 34 | end 35 | end 36 | 37 | if max.nil? || sum > max 38 | max = sum 39 | max_x = x 40 | max_y = y 41 | end 42 | end 43 | end 44 | 45 | puts [max_x, max_y].inspect 46 | -------------------------------------------------------------------------------- /2018/day-12/day-12-input.txt: -------------------------------------------------------------------------------- 1 | initial state: ####..##.##..##..#..###..#....#.######..###########.#...#.##..####.###.#.###.###..#.####..#.#..##..# 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 | .##.# => # -------------------------------------------------------------------------------- /2018/day-12/day-12-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | generations = 20 7 | 8 | input = input.split("\n") 9 | 10 | state = input[0] 11 | num_pots = (state.size + generations) * 2 12 | pots = Array.new(num_pots, ".") 13 | 14 | state.split(" ").last.chars.each_with_index do |pot, idx| 15 | pots[idx + num_pots / 2] = pot 16 | end 17 | 18 | rules = {} 19 | 20 | input[2..-1].each do |rule| 21 | pattern, pot = rule.split(" => ") 22 | 23 | rules[pattern] = pot 24 | end 25 | 26 | generations.times do 27 | next_pots = Array.new(num_pots, ".") 28 | 29 | pots.each_cons(5).with_index do |pots, idx| 30 | patern = pots.join 31 | result = rules[patern] 32 | next_pots[idx + 2] = result || "." 33 | end 34 | 35 | pots = next_pots 36 | end 37 | 38 | sum = 0 39 | 40 | pots.each.with_index do |pot, idx| 41 | sum += idx - num_pots / 2 if pot == "#" 42 | end 43 | 44 | puts sum 45 | -------------------------------------------------------------------------------- /2018/day-14/day-14-input.txt: -------------------------------------------------------------------------------- 1 | 236021 -------------------------------------------------------------------------------- /2018/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | scores = [3, 7] 7 | 8 | one = 0 9 | two = 1 10 | 11 | target = input.to_i 12 | 13 | while scores.length < (target + 10) do 14 | sum = scores[one] + scores[two] 15 | 16 | scores.concat(sum.to_s.chars.map(&:to_i)) 17 | 18 | one += 1 + scores[one] 19 | two += 1 + scores[two] 20 | 21 | one %= scores.length 22 | two %= scores.length 23 | end 24 | 25 | puts scores[-10..-1].join 26 | -------------------------------------------------------------------------------- /2018/day-14/day-14-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | scores = [3, 7] 7 | 8 | one = 0 9 | two = 1 10 | 11 | target = input.chars.map(&:to_i) 12 | 13 | last = [] 14 | 15 | loop do 16 | sum = scores[one] + scores[two] 17 | 18 | sum.to_s.chars.map(&:to_i).each do |a| 19 | scores << a 20 | last << a 21 | 22 | if last.length == target.length && last == target 23 | puts scores.length - target.length 24 | exit 25 | elsif last.length >= target.length 26 | last.shift 27 | end 28 | end 29 | 30 | one += 1 + scores[one] 31 | two += 1 + scores[two] 32 | 33 | one %= scores.length 34 | two %= scores.length 35 | 36 | puts scores.length if scores.length % 1_000_000 == 0 37 | end 38 | -------------------------------------------------------------------------------- /2018/day-19/day-19-input.txt: -------------------------------------------------------------------------------- 1 | #ip 3 2 | addi 3 16 3 3 | seti 1 3 1 4 | seti 1 2 4 5 | mulr 1 4 5 6 | eqrr 5 2 5 7 | addr 5 3 3 8 | addi 3 1 3 9 | addr 1 0 0 10 | addi 4 1 4 11 | gtrr 4 2 5 12 | addr 3 5 3 13 | seti 2 6 3 14 | addi 1 1 1 15 | gtrr 1 2 5 16 | addr 5 3 3 17 | seti 1 0 3 18 | mulr 3 3 3 19 | addi 2 2 2 20 | mulr 2 2 2 21 | mulr 3 2 2 22 | muli 2 11 2 23 | addi 5 8 5 24 | mulr 5 3 5 25 | addi 5 6 5 26 | addr 2 5 2 27 | addr 3 0 3 28 | seti 0 5 3 29 | setr 3 0 5 30 | mulr 5 3 5 31 | addr 3 5 5 32 | mulr 3 5 5 33 | muli 5 14 5 34 | mulr 5 3 5 35 | addr 2 5 2 36 | seti 0 8 0 37 | seti 0 9 3 -------------------------------------------------------------------------------- /2018/day-21/day-21-input.txt: -------------------------------------------------------------------------------- 1 | #ip 1 2 | seti 123 0 5 3 | bani 5 456 5 4 | eqri 5 72 5 5 | addr 5 1 1 6 | seti 0 0 1 7 | seti 0 7 5 8 | bori 5 65536 4 9 | seti 13159625 6 5 10 | bani 4 255 3 11 | addr 5 3 5 12 | bani 5 16777215 5 13 | muli 5 65899 5 14 | bani 5 16777215 5 15 | gtir 256 4 3 16 | addr 3 1 1 17 | addi 1 1 1 18 | seti 27 9 1 19 | seti 0 0 3 20 | addi 3 1 2 21 | muli 2 256 2 22 | gtrr 2 4 2 23 | addr 2 1 1 24 | addi 1 1 1 25 | seti 25 0 1 26 | addi 3 1 3 27 | seti 17 4 1 28 | setr 3 3 4 29 | seti 7 5 1 30 | eqrr 5 0 3 31 | addr 3 1 1 32 | seti 5 6 1 -------------------------------------------------------------------------------- /2018/day-21/day-21-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-21-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | # Reverse engineer and optimise - a = reg[4], b = reg[5] 9 | def activation_system(input) 10 | b = input 11 | 12 | a = b | 65536 13 | b = 13159625 14 | 15 | while a > 0 16 | b += a & 255 17 | b &= 16777215 18 | 19 | b *= 65899 20 | b &= 16777215 21 | 22 | a /= 256 23 | end 24 | 25 | b 26 | end 27 | 28 | # It should halt before an infinite loop, identity when that is 29 | visited = Set.new 30 | 31 | input = 0 32 | 33 | loop do 34 | visited.add(input) 35 | 36 | output = activation_system(input) 37 | 38 | if visited.include?(output) 39 | puts input 40 | exit 41 | end 42 | 43 | input = output 44 | end 45 | -------------------------------------------------------------------------------- /2018/day-22/day-22-input.txt: -------------------------------------------------------------------------------- 1 | depth: 3339 2 | target: 10,715 -------------------------------------------------------------------------------- /2018/day-22/day-22-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-22-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | depth, target = input.split("\n") 7 | 8 | depth = depth.scan(/\d+/)[0].to_i 9 | xt, yt = target.scan(/\d+/).map(&:to_i) 10 | 11 | length = yt + 1 12 | width = xt + 1 13 | 14 | map = Array.new(length) { Array.new(width) } 15 | 16 | map[0][0] = 0 17 | map[yt][xt] = 0 18 | 19 | length.times do |y| 20 | map[y][0] = (y * 48271 + depth) % 20183 21 | end 22 | 23 | width.times do |x| 24 | map[0][x] = (x * 16807 + depth) % 20183 25 | end 26 | 27 | length.times do |y| 28 | next if y == 0 29 | width.times do |x| 30 | next if x == 0 || x == xt && y == yt 31 | map[y][x] = ((map[y-1][x] * map[y][x-1]) + depth) % 20183 32 | end 33 | end 34 | 35 | length.times do |y| 36 | width.times do |x| 37 | map[y][x] %= 3 38 | end 39 | end 40 | 41 | puts map.flatten.inject(:+) 42 | -------------------------------------------------------------------------------- /2018/day-23/day-23-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-23-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | bots = input.split("\n") 7 | 8 | class Bot 9 | attr_reader :x, :y, :z, :r 10 | 11 | def initialize(x, y, z, r) 12 | @x = x 13 | @y = y 14 | @z = z 15 | @r = r 16 | end 17 | 18 | def distance(other) 19 | (other.x - x).abs + 20 | (other.y - y).abs + 21 | (other.z - z).abs 22 | end 23 | 24 | def within_range?(other) 25 | distance(other) <= r 26 | end 27 | end 28 | 29 | bots.map! do |bot| 30 | x, y, z, r = bot.scan(/-*\d+/).map(&:to_i) 31 | 32 | Bot.new(x, y, z, r) 33 | end 34 | 35 | puts bots.map { |bot| 36 | bots.count { |other| bot.within_range?(other) } 37 | }.max 38 | -------------------------------------------------------------------------------- /2018/day-25/day-25-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-25-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | constellations = [] 7 | 8 | points = input.split("\n").map do |line| 9 | line.split(",").map(&:to_i) 10 | end 11 | 12 | def distance(point, other) 13 | point.zip(other) 14 | .map { |(p1, p2)| (p1 - p2).abs } 15 | .inject(:+) 16 | end 17 | 18 | points.each do |point| 19 | matches = constellations.select do |constellation| 20 | constellation.any? { |other_point| distance(point, other_point) <= 3 } 21 | end 22 | 23 | case matches.count 24 | when 0 25 | constellations << [point] 26 | when 1 27 | matches.first << point 28 | else 29 | matches.each { |constellation| constellations.delete(constellation) } 30 | constellation = matches.inject(&:concat) << point 31 | constellations << constellation 32 | end 33 | end 34 | 35 | puts constellations.count 36 | -------------------------------------------------------------------------------- /2019/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | fuel = 0 7 | 8 | modules = input.split("\n").map(&:to_i) 9 | 10 | modules.each do |mass| 11 | fuel += mass / 3 - 2 12 | end 13 | 14 | puts fuel 15 | -------------------------------------------------------------------------------- /2019/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | fuel = 0 7 | 8 | modules = input.split("\n").map(&:to_i) 9 | 10 | modules.each do |mass| 11 | while mass > 0 12 | mass = mass / 3 - 2 13 | fuel += mass 14 | end 15 | end 16 | 17 | puts fuel 18 | -------------------------------------------------------------------------------- /2019/day-02/day-02-input.txt: -------------------------------------------------------------------------------- 1 | 1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,6,1,19,1,19,5,23,2,9,23,27,1,5,27,31,1,5,31,35,1,35,13,39,1,39,9,43,1,5,43,47,1,47,6,51,1,51,13,55,1,55,9,59,1,59,13,63,2,63,13,67,1,67,10,71,1,71,6,75,2,10,75,79,2,10,79,83,1,5,83,87,2,6,87,91,1,91,6,95,1,95,13,99,2,99,13,103,1,103,9,107,1,10,107,111,2,111,13,115,1,10,115,119,1,10,119,123,2,13,123,127,2,6,127,131,1,13,131,135,1,135,2,139,1,139,6,0,99,2,0,14,0 2 | -------------------------------------------------------------------------------- /2019/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | codes = input.split(",").map(&:to_i) 7 | 8 | codes[1] = 12 9 | codes[2] = 2 10 | 11 | i = 0 12 | 13 | loop do 14 | case codes[i] 15 | when 1 16 | op = :+ 17 | when 2 18 | op = :* 19 | when 99 20 | puts codes[0] 21 | exit 22 | end 23 | 24 | codes[codes[i+3]] = codes[codes[i+1]].send(op, codes[codes[i+2]]) 25 | 26 | i += 4 27 | end 28 | -------------------------------------------------------------------------------- /2019/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | codes = input.split(",").map(&:to_i) 7 | 8 | def run(noun, verb, codes) 9 | codes[1] = noun 10 | codes[2] = verb 11 | 12 | i = 0 13 | 14 | loop do 15 | case codes[i] 16 | when 1 17 | op = :+ 18 | when 2 19 | op = :* 20 | when 99 21 | return codes[0] 22 | end 23 | 24 | codes[codes[i+3]] = codes[codes[i+1]].send(op, codes[codes[i+2]]) 25 | 26 | i += 4 27 | end 28 | end 29 | 30 | 100.times do |n| 31 | 100.times do |v| 32 | result = run(n, v, codes.clone) 33 | if result == 19690720 34 | puts 100 * n + v 35 | exit 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /2019/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | def walk(path) 9 | visited = Set.new 10 | x, y = 0, 0 11 | 12 | path.split(",").each do |instr| 13 | dir = instr[0] 14 | steps = instr[1..].to_i 15 | 16 | steps.times do 17 | case dir 18 | when "U" 19 | y += 1 20 | when "D" 21 | y -= 1 22 | when"L" 23 | x -= 1 24 | when "R" 25 | x += 1 26 | end 27 | 28 | visited.add [x,y] 29 | end 30 | end 31 | 32 | visited 33 | end 34 | 35 | path_one, path_two = input.split("\n") 36 | 37 | intersection = walk(path_one) & walk(path_two) 38 | 39 | puts intersection. 40 | map { |x, y| x.abs + y.abs }. 41 | min 42 | -------------------------------------------------------------------------------- /2019/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | def walk(path) 7 | visited = {} 8 | x, y = 0, 0 9 | step = 1 10 | 11 | path.split(",").each do |instr| 12 | dir = instr[0] 13 | steps = instr[1..].to_i 14 | 15 | steps.times do 16 | case dir 17 | when "U" 18 | y += 1 19 | when "D" 20 | y -= 1 21 | when"L" 22 | x -= 1 23 | when "R" 24 | x += 1 25 | end 26 | 27 | visited[[x,y]] = step unless visited[[x,y]] 28 | step += 1 29 | end 30 | end 31 | 32 | visited 33 | end 34 | 35 | path_one, path_two = input.split("\n") 36 | 37 | visited_one = walk(path_one) 38 | visited_two = walk(path_two) 39 | 40 | intersection = visited_one.keys & visited_two.keys 41 | 42 | puts intersection. 43 | map { |x, y| visited_one[[x,y]] + visited_two[[x,y]] }. 44 | min 45 | -------------------------------------------------------------------------------- /2019/day-04/day-04-input.txt: -------------------------------------------------------------------------------- 1 | 264793-803935 2 | -------------------------------------------------------------------------------- /2019/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | from, to = input.split("-").map(&:to_i) 7 | 8 | count = 0 9 | 10 | (from..to).each do |pw| 11 | digits = pw.digits 12 | 13 | increasing = digits.each_cons(2).all? do |a, b| 14 | a >= b 15 | end 16 | 17 | adjacent = digits.each_cons(2).any? do |a, b| 18 | a == b 19 | end 20 | 21 | count += 1 if increasing && adjacent 22 | end 23 | 24 | puts count 25 | -------------------------------------------------------------------------------- /2019/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | from, to = input.split("-").map(&:to_i) 7 | 8 | count = 0 9 | 10 | (from..to).each do |pw| 11 | digits = pw.to_i.digits 12 | 13 | increasing = digits.each_cons(2).all? do |a, b| 14 | a >= b 15 | end 16 | 17 | double = digits.chunk(&:itself).any? do |_, chunk| 18 | chunk.size == 2 19 | end 20 | 21 | count += 1 if increasing && double 22 | end 23 | 24 | puts count 25 | -------------------------------------------------------------------------------- /2019/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | codes = input.split(",").map(&:to_i) 7 | inp = 1 8 | 9 | i = 0 10 | 11 | loop do 12 | opcode = codes[i] % 100 13 | 14 | modes = (codes[i] / 100).digits 15 | 3.times { modes << 0 } 16 | 17 | refs = modes.map.with_index do |m, idx| 18 | address = i + idx + 1 19 | 20 | if m == 1 21 | address 22 | else 23 | codes[address] 24 | end 25 | end 26 | 27 | case opcode 28 | when 1 29 | op = :+ 30 | when 2 31 | op = :* 32 | when 3 33 | codes[refs[0]] = inp 34 | when 4 35 | puts codes[refs[0]] 36 | when 99 37 | exit 38 | end 39 | 40 | codes[refs[2]] = codes[refs[0]].send(op, codes[refs[1]]) if op 41 | 42 | if [1, 2].include?(opcode) 43 | i += 4 44 | else 45 | i += 2 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /2019/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | orbits = {} 7 | 8 | input.split("\n").each do |orbit| 9 | a, b = orbit.split(")") 10 | 11 | orbits[b] = a 12 | end 13 | 14 | count = 0 15 | 16 | orbits.each do |obj, _| 17 | while orbits[obj] 18 | obj = orbits[obj] 19 | count += 1 20 | end 21 | end 22 | 23 | puts count 24 | -------------------------------------------------------------------------------- /2019/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | orbits = {} 7 | 8 | input.split("\n").each do |orbit| 9 | a, b = orbit.split(")") 10 | 11 | orbits[b] = a 12 | end 13 | 14 | def path(orbits, from) 15 | path = [] 16 | 17 | while orbits[from] 18 | from = orbits[from] 19 | path << from 20 | end 21 | 22 | path 23 | end 24 | 25 | you_path = path(orbits, "YOU") 26 | santa_path = path(orbits, "SAN") 27 | 28 | intersect = you_path.find do |obj| 29 | santa_path.include?(obj) 30 | end 31 | 32 | puts you_path.index(intersect) + santa_path.index(intersect) 33 | -------------------------------------------------------------------------------- /2019/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | input = File.read(file_path).strip 5 | 6 | height = 6 7 | width = 25 8 | 9 | area = height * width 10 | 11 | layers = input.chars.map(&:to_i).each_slice(area) 12 | 13 | layer = layers.min_by do |layer| 14 | layer.count { |pixel| pixel.zero? } 15 | end 16 | 17 | puts layer.count { |pixel| pixel == 1 } * 18 | layer.count { |pixel| pixel == 2 } 19 | -------------------------------------------------------------------------------- /2019/day-08/day-08-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | input = File.read(file_path).strip 5 | 6 | height = 6 7 | width = 25 8 | 9 | area = height * width 10 | 11 | layers = input.chars.map(&:to_i).each_slice(area) 12 | 13 | area.times do |i| 14 | layer = layers.find do |layer| 15 | pixel = layer[i] 16 | pixel == 0 || pixel == 1 17 | end 18 | 19 | print (layer[i] == 0 ? " " : "#") 20 | puts if (i + 1) % width == 0 21 | end 22 | -------------------------------------------------------------------------------- /2019/day-12/day-12-input.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /2019/day-16/day-16-input.txt: -------------------------------------------------------------------------------- 1 | 59776034095811644545367793179989602140948714406234694972894485066523525742503986771912019032922788494900655855458086979764617375580802558963587025784918882219610831940992399201782385674223284411499237619800193879768668210162176394607502218602633153772062973149533650562554942574593878073238232563649673858167635378695190356159796342204759393156294658366279922734213385144895116649768185966866202413314939692174223210484933678866478944104978890019728562001417746656699281992028356004888860103805472866615243544781377748654471750560830099048747570925902575765054898899512303917159138097375338444610809891667094051108359134017128028174230720398965960712 2 | -------------------------------------------------------------------------------- /2019/day-16/day-16-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-16-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | digits = input.chars.map(&:to_i) * 10000 7 | 8 | offset = digits[0, 7].join.to_i 9 | 10 | digits = digits[offset..] 11 | 12 | 100.times do |time| 13 | result = [] 14 | 15 | # Bottom half digits is a triangular matrix. 16 | # From the offset, we are certainly in the bottom half. 17 | sum = digits.inject(:+) 18 | 19 | digits.length.times do |i| 20 | result << sum.abs % 10 21 | 22 | sum -= digits[i] 23 | end 24 | 25 | digits = result 26 | end 27 | 28 | puts digits[0, 8].join 29 | -------------------------------------------------------------------------------- /2019/day-22/day-22-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-22-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | deck_size = 10007 7 | 8 | deck = (0..deck_size-1).to_a 9 | 10 | input.each_line do |line| 11 | if line.match(/deal into new stack/) 12 | deck.reverse! 13 | elsif line.match(/cut (-*\d+)/) 14 | cut = $1.to_i 15 | deck.rotate!(cut) 16 | elsif line.match(/deal with increment (\d+)/) 17 | incr = $1.to_i 18 | 19 | deck_copy = Array.new(deck_size) 20 | 21 | deck_size.times do |card| 22 | deck_copy[(card * incr) % deck_size] = deck[card] 23 | end 24 | 25 | deck = deck_copy 26 | end 27 | end 28 | 29 | puts deck.index(2019) 30 | -------------------------------------------------------------------------------- /2020/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | set = input.split("\n").map(&:to_i).to_set 9 | 10 | set.each do |x| 11 | expect = 2020 - x 12 | 13 | if set.include?(expect) 14 | puts expect * x 15 | break 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /2020/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | set = input.split("\n").map(&:to_i).to_set 9 | 10 | set.to_a.combination(2) do |v, w| 11 | expect = 2020 - v - w 12 | 13 | if set.include?(expect) 14 | puts expect * v * w 15 | break 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /2020/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n").count { |line| 7 | policy, password = line.split(":").map(&:strip) 8 | 9 | counts, char = policy.split(" ") 10 | min, max = counts.split("-").map(&:to_i) 11 | 12 | char_count = password.chars.count { |c| c == char } 13 | 14 | (min..max).cover?(char_count) 15 | } 16 | -------------------------------------------------------------------------------- /2020/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n").count { |line| 7 | policy, password = line.split(":").map(&:strip) 8 | 9 | counts, char = policy.split(" ") 10 | pos_1, pos_2 = counts.split("-").map(&:to_i) 11 | 12 | (password[pos_1 - 1] == char) ^ (password[pos_2 - 1] == char) 13 | } 14 | -------------------------------------------------------------------------------- /2020/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-03-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | map = input.split("\n").map { |line| line.split('') } 7 | 8 | x, y, trees = 0, 0, 0 9 | dx = 3 10 | dy = 1 11 | 12 | while y < map.length - 1 13 | x += dx 14 | x %= map[0].length 15 | y += dy 16 | 17 | trees += 1 if map[y][x] == '#' 18 | end 19 | 20 | puts trees 21 | -------------------------------------------------------------------------------- /2020/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-03-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | map = input.split("\n").map { |line| line.split('') } 7 | 8 | slopes = [[1, 1], [3, 1], [5, 1], [7, 1], [1, 2]] 9 | 10 | puts slopes.map { |dx, dy| 11 | x = 0 12 | y = 0 13 | trees = 0 14 | 15 | while y < map.length - 1 16 | x += dx 17 | x %= map[0].length 18 | y += dy 19 | 20 | trees += 1 if map[y][x] == '#' 21 | end 22 | 23 | trees 24 | }.reduce(:*) 25 | -------------------------------------------------------------------------------- /2020/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-04-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | passes = input.split("\n\n") 7 | 8 | expect = %w(byr iyr eyr hgt hcl ecl pid) 9 | 10 | puts passes.count { |pass| 11 | expect.all? { |field| pass.match?(/#{field}:\S+/) } 12 | } 13 | -------------------------------------------------------------------------------- /2020/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-04-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | passes = input.split("\n\n") 7 | 8 | expect = { 9 | byr: 1920..2002, 10 | iyr: 2010..2020, 11 | eyr: 2020..2040, 12 | hgt: /1([5-8]\d|9[0-3])cm|(59|6\d|7[0-6])in/, 13 | hcl: /#[0-9a-f]{6}/, 14 | ecl: /(amb|blu|brn|gry|grn|hzl|oth)/, 15 | pid: /\d{9}/ 16 | }.transform_keys(&:to_s) 17 | 18 | puts passes.count { |pass| 19 | fields = Hash[ 20 | pass.split(/\s/).map { |field| field.split(":") } 21 | ] 22 | 23 | expect.all? do |k, v| 24 | field = fields[k] 25 | 26 | next unless field 27 | 28 | if v.is_a?(Regexp) 29 | field.match?(/\A#{v}\z/) 30 | else 31 | v.cover?(field.to_i) 32 | end 33 | end 34 | } 35 | -------------------------------------------------------------------------------- /2020/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-05-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | seats = input.split("\n") 7 | 8 | ids = seats.map do |seat| 9 | rmin, rmax = 0, 127 10 | cmin, cmax = 0, 7 11 | 12 | seat.split("").each do |c| 13 | ri = (rmin + rmax) / 2 14 | ci = (cmin + cmax) / 2 15 | 16 | case c 17 | when ?F 18 | rmax = ri 19 | when ?B 20 | rmin = ri + 1 21 | when ?L 22 | cmax = ci 23 | when ?R 24 | cmin = ci + 1 25 | end 26 | end 27 | 28 | rmin * 8 + cmin 29 | end 30 | 31 | puts ids.max 32 | -------------------------------------------------------------------------------- /2020/day-05/day-05-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path('day-05-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | seats = input.split("\n") 9 | 10 | ids = seats.map do |seat| 11 | rmin, rmax = 0, 127 12 | cmin, cmax = 0, 7 13 | 14 | seat.split("").each do |c| 15 | ri = (rmin + rmax) / 2 16 | ci = (cmin + cmax) / 2 17 | 18 | case c 19 | when ?F 20 | rmax = ri 21 | when ?B 22 | rmin = ri + 1 23 | when ?L 24 | cmax = ci 25 | when ?R 26 | cmin = ci + 1 27 | end 28 | end 29 | 30 | rmin * 8 + cmin 31 | end 32 | 33 | ids = Set.new(ids) 34 | 35 | puts (ids.min..ids.max).find { |id| 36 | ids.include?(id - 1) && ids.include?(id + 1) && !ids.include?(id) 37 | } 38 | -------------------------------------------------------------------------------- /2020/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-06-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | groups = input.split("\n\n") 7 | 8 | puts groups 9 | .map { |g| g.gsub(/\s/, '').chars.uniq.count } 10 | .sum 11 | -------------------------------------------------------------------------------- /2020/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-06-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | groups = input.split("\n\n") 7 | 8 | puts groups.map { |g| 9 | qs = g.gsub(/\s/, '').chars.uniq 10 | 11 | qs.count do |q| 12 | g.split("\n").all? { |line| line.include?(q) } 13 | end 14 | }.sum 15 | 16 | -------------------------------------------------------------------------------- /2020/day-07/day-07-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path('day-07-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | parent_bag = Hash.new { |hash, key| hash[key] = Array.new } 9 | 10 | input.split("\n").each do |line| 11 | parent, contain = line.match(/(\w+ \w+) bags contain (.*)\./)[1..2] 12 | 13 | children = contain.split(",") 14 | .map { |child| child.match(/(\w+ \w+) bag/)[1] } 15 | .compact 16 | 17 | children.each do |child| 18 | parent_bag[child] << parent 19 | end 20 | end 21 | 22 | bag_colours = Set.new 23 | queue = ["shiny gold"] 24 | 25 | while queue.any? 26 | child = queue.shift 27 | 28 | parent_bag[child].each do |parent| 29 | bag_colours.add(parent) 30 | queue << parent 31 | end 32 | end 33 | 34 | puts bag_colours.size 35 | -------------------------------------------------------------------------------- /2020/day-07/day-07-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-07-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | children_bags = {} 7 | 8 | input.split("\n").each do |line| 9 | parent, contain = line.match(/(\w+ \w+) bags contain (.*)\./)[1..2] 10 | 11 | children = contain.split(",") 12 | .reject { |child| child.include?("no other") } 13 | .map { |child| 14 | [ 15 | child.match(/\d+/)[0].to_i, 16 | child.match(/(\w+ \w+) bag/)[1] 17 | ] 18 | } 19 | 20 | children_bags[parent] = children 21 | end 22 | 23 | sum = 0 24 | queue = [["shiny gold", 1]] 25 | 26 | while queue.any? 27 | parent, parent_count = queue.shift 28 | 29 | children_bags[parent].each do |child_count, child| 30 | sum += child_count * parent_count 31 | queue << [child, child_count * parent_count] 32 | end 33 | end 34 | 35 | puts sum 36 | -------------------------------------------------------------------------------- /2020/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path('day-08-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | ops = input.split("\n") 9 | 10 | i = 0 11 | acc = 0 12 | executed = Set.new 13 | 14 | while true 15 | if executed.include?(i) 16 | puts acc 17 | exit 18 | end 19 | 20 | executed.add(i) 21 | 22 | op, arg = ops[i].split 23 | arg = arg.to_i 24 | 25 | case op 26 | when "acc" 27 | acc += arg 28 | when "jmp" 29 | i += arg - 1 30 | end 31 | 32 | i += 1 33 | end 34 | -------------------------------------------------------------------------------- /2020/day-08/day-08-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path('day-08-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | def run(ops) 9 | i = 0 10 | acc = 0 11 | executed = Set.new 12 | 13 | while i < ops.size 14 | return nil if executed.include?(i) 15 | executed.add(i) 16 | 17 | op, arg = ops[i].split 18 | arg = arg.to_i 19 | 20 | case op 21 | when "acc" 22 | acc += arg 23 | when "jmp" 24 | i += arg - 1 25 | end 26 | 27 | i += 1 28 | end 29 | 30 | acc 31 | end 32 | 33 | ops = input.split("\n") 34 | 35 | ops.size.times do |i| 36 | fixed_ops = ops.map(&:clone) 37 | 38 | instr = fixed_ops[i] 39 | 40 | if instr =~ /jmp/ 41 | instr.gsub!("jmp", "nop") 42 | elsif instr =~ /nop/ 43 | instr.gsub!("nop", "jmp") 44 | else 45 | next 46 | end 47 | 48 | acc = run(fixed_ops) 49 | 50 | if acc 51 | puts acc 52 | exit 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /2020/day-09/day-09-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes both part 1 and part 2 solutions 4 | 5 | file_path = File.expand_path('day-09-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | step = 25 9 | 10 | data = input.split("\n").map(&:to_i) 11 | 12 | invalid, _ = data.find.with_index do |sum, i| 13 | next if i < step 14 | 15 | data[i - step, step] 16 | .combination(2).none? { |pair| pair.sum == sum } 17 | end 18 | 19 | puts invalid 20 | 21 | data.size.times do |i| 22 | j = i + 1 23 | 24 | while true 25 | range = data[i..j] 26 | sum = range.sum 27 | 28 | if sum == invalid 29 | puts range.minmax.sum 30 | exit 31 | end 32 | 33 | break if sum > invalid 34 | j += 1 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /2020/day-09/day-09-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes both part 1 and part 2 solutions 4 | 5 | file_path = File.expand_path('day-09-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | step = 25 9 | 10 | data = input.split("\n").map(&:to_i) 11 | 12 | invalid, _ = data.find.with_index do |sum, i| 13 | next if i < step 14 | 15 | data[i - step, step] 16 | .combination(2).none? { |pair| pair.sum == sum } 17 | end 18 | 19 | puts invalid 20 | 21 | data.size.times do |i| 22 | j = i + 1 23 | 24 | while true 25 | range = data[i..j] 26 | sum = range.sum 27 | 28 | if sum == invalid 29 | puts range.minmax.sum 30 | exit 31 | end 32 | 33 | break if sum > invalid 34 | j += 1 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /2020/day-10/day-10-input.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 40 3 | 45 4 | 93 5 | 147 6 | 64 7 | 90 8 | 125 9 | 149 10 | 145 11 | 111 12 | 126 13 | 9 14 | 146 15 | 38 16 | 97 17 | 103 18 | 6 19 | 122 20 | 34 21 | 18 22 | 35 23 | 96 24 | 86 25 | 116 26 | 29 27 | 59 28 | 118 29 | 102 30 | 26 31 | 66 32 | 17 33 | 74 34 | 94 35 | 5 36 | 114 37 | 128 38 | 1 39 | 75 40 | 47 41 | 141 42 | 58 43 | 65 44 | 100 45 | 63 46 | 12 47 | 53 48 | 25 49 | 106 50 | 136 51 | 15 52 | 82 53 | 22 54 | 117 55 | 2 56 | 80 57 | 79 58 | 139 59 | 7 60 | 81 61 | 129 62 | 19 63 | 52 64 | 87 65 | 115 66 | 132 67 | 140 68 | 88 69 | 109 70 | 62 71 | 73 72 | 46 73 | 24 74 | 69 75 | 101 76 | 110 77 | 16 78 | 95 79 | 148 80 | 76 81 | 135 82 | 142 83 | 89 84 | 50 85 | 72 86 | 41 87 | 39 88 | 42 89 | 56 90 | 51 91 | 57 92 | 127 93 | 83 94 | 121 95 | 33 96 | 32 97 | 23 98 | 99 | -------------------------------------------------------------------------------- /2020/day-10/day-10-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes both part 1 and part 2 solutions 4 | 5 | file_path = File.expand_path('day-10-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | adapters = input.split("\n").map(&:to_i).sort 9 | 10 | adapters.unshift(0) 11 | adapters << adapters.last + 3 12 | 13 | diffs = Hash.new(0) 14 | 15 | adapters.each_cons(2) do |a, b| 16 | diff = b - a 17 | diffs[diff] += 1 18 | end 19 | 20 | puts diffs[1] * diffs[3] 21 | 22 | 23 | pos = Hash.new(0) 24 | pos[0] = 1 25 | 26 | adapters.each do |a| 27 | 3.times do |i| 28 | pos[a] += pos[a - i - 1] 29 | end 30 | end 31 | 32 | puts pos.values.max 33 | -------------------------------------------------------------------------------- /2020/day-10/day-10-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes both part 1 and part 2 solutions 4 | 5 | file_path = File.expand_path('day-10-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | adapters = input.split("\n").map(&:to_i).sort 9 | 10 | adapters.unshift(0) 11 | adapters << adapters.last + 3 12 | 13 | diffs = Hash.new(0) 14 | 15 | adapters.each_cons(2) do |a, b| 16 | diff = b - a 17 | diffs[diff] += 1 18 | end 19 | 20 | puts diffs[1] * diffs[3] 21 | 22 | 23 | pos = Hash.new(0) 24 | pos[0] = 1 25 | 26 | adapters.each do |a| 27 | 3.times do |i| 28 | pos[a] += pos[a - i - 1] 29 | end 30 | end 31 | 32 | puts pos.values.max 33 | -------------------------------------------------------------------------------- /2020/day-12/day-12-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-12-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | x, y = 0, 0 9 | facing = [1, 0] 10 | 11 | def turn(dir, deg) 12 | turns = deg / 90 13 | dirs = [[0, -1], [-1, 0], [0, 1], [1, 0]] 14 | idx = dirs.index(dir) + turns 15 | dirs[idx % 4] 16 | end 17 | 18 | lines.each do |cmd| 19 | action, val = cmd.match(/(\w)(\d+)/).captures 20 | 21 | val = val.to_i 22 | 23 | case action 24 | when ?N 25 | y -= val 26 | when ?E 27 | x += val 28 | when ?S 29 | y += val 30 | when ?W 31 | x -= val 32 | when ?L 33 | facing = turn(facing, val) 34 | when ?R 35 | facing = turn(facing, -val) 36 | when ?F 37 | x += val * facing[0] 38 | y += val * facing[1] 39 | end 40 | end 41 | 42 | puts [x, y].map(&:abs).sum 43 | -------------------------------------------------------------------------------- /2020/day-12/day-12-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-12-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | x, y = 0, 0 7 | x1, y1 = [10, -1] 8 | 9 | def rotate(x, y, deg) 10 | { 11 | 90 => [-y, x], 12 | 270 => [y, -x], 13 | 180 => [-x, -y], 14 | }[(deg + 360) % 360] 15 | end 16 | 17 | input.split("\n").each do |cmd| 18 | action, val = cmd.match(/(\w)(\d+)/).captures 19 | 20 | val = val.to_i 21 | 22 | case action 23 | when ?N 24 | y1 -= val 25 | when ?E 26 | x1 += val 27 | when ?S 28 | y1 += val 29 | when ?W 30 | x1 -= val 31 | when ?L 32 | x1, y1 = rotate(x1, y1, -val) 33 | when ?R 34 | x1, y1 = rotate(x1, y1, val) 35 | when ?F 36 | x += val * x1 37 | y += val * y1 38 | end 39 | end 40 | 41 | puts [x, y].map(&:abs).sum 42 | -------------------------------------------------------------------------------- /2020/day-13/day-13-input.txt: -------------------------------------------------------------------------------- 1 | 1001287 2 | 13,x,x,x,x,x,x,37,x,x,x,x,x,461,x,x,x,x,x,x,x,x,x,x,x,x,x,17,x,x,x,x,19,x,x,x,x,x,x,x,x,x,29,x,739,x,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,x,x,x,x,23 3 | -------------------------------------------------------------------------------- /2020/day-13/day-13-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-13-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | earliest, buses = input.split("\n") 7 | 8 | earliest = earliest.to_i 9 | buses = buses.split(",").reject { |id| id == ?x }.map(&:to_i) 10 | 11 | depart, id = buses.map { |id| 12 | [ 13 | (earliest.to_f / id).ceil * id, 14 | id 15 | ] 16 | }.min 17 | 18 | puts (depart - earliest) * id 19 | -------------------------------------------------------------------------------- /2020/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-14-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | mem = {} 9 | mask = nil 10 | 11 | lines.each do |line| 12 | if line.include?("mask") 13 | mask = line.match(/= (.*)/).captures.first 14 | else 15 | idx, val = line.match(/\[(\d+)\] = (\d+)/).captures 16 | 17 | idx = idx.to_i 18 | val = val.to_i.to_s(2) 19 | 20 | result = mask.reverse.chars.zip(val.reverse.chars).map do |m, v| 21 | if m != ?X 22 | m 23 | else 24 | v || 0 25 | end 26 | end 27 | 28 | mem[idx] = result.reverse.join.to_i(2) 29 | end 30 | end 31 | 32 | puts mem.values.sum 33 | -------------------------------------------------------------------------------- /2020/day-15/day-15-input.txt: -------------------------------------------------------------------------------- 1 | 0,5,4,1,10,14,7 2 | -------------------------------------------------------------------------------- /2020/day-15/day-15-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes both part 1 and part 2 solutions 4 | 5 | file_path = File.expand_path('day-15-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | nums = input.split(",").map(&:to_i) 9 | 10 | spoken = Hash.new { |h, k| h[k] = Array.new } 11 | 12 | nums.each.with_index do |i, idx| 13 | spoken[i] << idx 14 | end 15 | 16 | idx = nums.count 17 | last = nums.last 18 | 19 | while idx < 30000000 20 | if spoken[last].count > 1 21 | last = spoken[last].last(2).inject(:-).abs 22 | else 23 | last = 0 24 | end 25 | 26 | spoken[last] << idx 27 | 28 | idx += 1 29 | 30 | puts last if idx == 2020 31 | end 32 | 33 | puts last 34 | -------------------------------------------------------------------------------- /2020/day-15/day-15-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Includes both part 1 and part 2 solutions 4 | 5 | file_path = File.expand_path('day-15-input.txt', __dir__) 6 | input = File.read(file_path) 7 | 8 | nums = input.split(",").map(&:to_i) 9 | 10 | spoken = Hash.new { |h, k| h[k] = Array.new } 11 | 12 | nums.each.with_index do |i, idx| 13 | spoken[i] << idx 14 | end 15 | 16 | idx = nums.count 17 | last = nums.last 18 | 19 | while idx < 30000000 20 | if spoken[last].count > 1 21 | last = spoken[last].last(2).inject(:-).abs 22 | else 23 | last = 0 24 | end 25 | 26 | spoken[last] << idx 27 | 28 | idx += 1 29 | 30 | puts last if idx == 2020 31 | end 32 | 33 | puts last 34 | -------------------------------------------------------------------------------- /2020/day-17/day-17-input.txt: -------------------------------------------------------------------------------- 1 | ###...#. 2 | .##.#### 3 | .####.## 4 | ###.###. 5 | .##.#### 6 | #.##..#. 7 | ##.####. 8 | .####.#. 9 | -------------------------------------------------------------------------------- /2020/day-18/day-18-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-18-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | sum = 0 9 | 10 | def sum(exp) 11 | result = exp.shift.to_i 12 | 13 | exp.each_slice(2) do |op, num| 14 | result = result.send(op, num.to_i) 15 | end 16 | 17 | result 18 | end 19 | 20 | lines.each do |line| 21 | tokens = line.gsub(/\s/, '').chars 22 | 23 | stack = [] 24 | 25 | tokens.each do |token| 26 | if token =~ /[\d\*\+\(]+/ 27 | stack << token 28 | else # ?( 29 | exp = [] 30 | 31 | while stack.last != ?( 32 | exp << stack.pop 33 | end 34 | stack.pop # ?( 35 | 36 | result = sum(exp.reverse) 37 | 38 | stack << result 39 | end 40 | end 41 | 42 | sum += sum(stack) 43 | end 44 | 45 | puts sum 46 | -------------------------------------------------------------------------------- /2020/day-18/day-18-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-18-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | lines = input.split("\n") 7 | 8 | sum = 0 9 | 10 | lines.each do |line| 11 | tokens = line.gsub(/\s/, '').chars 12 | 13 | stack = [] 14 | 15 | tokens.each do |token| 16 | if token =~ /\d/ 17 | stack << token.to_i 18 | elsif token =~ /[\+\*\(]+/ 19 | stack << token 20 | else # ?( 21 | exp = [] 22 | 23 | while stack.last != ?( 24 | exp << stack.pop 25 | end 26 | stack.pop # ?( 27 | 28 | result = eval(exp.join) 29 | 30 | stack << result 31 | end 32 | 33 | while stack.last.is_a?(Integer) && stack[-2] == ?+ 34 | num1 = stack.pop 35 | stack.pop # ?+ 36 | num2 = stack.pop 37 | 38 | stack << num1 + num2 39 | end 40 | end 41 | 42 | sum += eval(stack.reverse.join) 43 | end 44 | 45 | puts sum 46 | -------------------------------------------------------------------------------- /2020/day-19/day-19-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-19-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | rules, msgs = input.split("\n\n") 7 | 8 | rule_map = {} 9 | 10 | rules.split("\n").each do |rule| 11 | key, rule = rule.split(": ") 12 | 13 | rule.gsub!(?", "") 14 | rule.gsub!(/(\d+)/, '[\1]') 15 | rule = "(#{rule})" if rule.include? ?| 16 | 17 | rule_map[key] = rule 18 | end 19 | 20 | while rule_map[?0] =~ /\d/ 21 | zero = rule_map[?0] 22 | rule = zero.scan(/\d+/)[0] 23 | zero.gsub!(/\[#{rule}\]/, rule_map[rule]) 24 | end 25 | 26 | rule_map[?0].gsub!(/\s/, '') 27 | regex = Regexp.new("^#{rule_map[?0]}$") 28 | 29 | puts msgs.split("\n").count { |msg| regex.match(msg) } 30 | 31 | -------------------------------------------------------------------------------- /2020/day-19/day-19-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path('day-19-input.txt', __dir__) 4 | input = File.read(file_path) 5 | 6 | rules, msgs = input.split("\n\n") 7 | 8 | rule_map = {} 9 | 10 | rules.split("\n").each do |rule| 11 | key, rule = rule.split(": ") 12 | 13 | rule.gsub!(?", "") 14 | rule.gsub!(/(\d+)/, '[\1]') 15 | rule = "(#{rule})" if rule.include? ?| 16 | 17 | rule_map[key] = rule 18 | end 19 | 20 | rule_map["8"] = "([42]+)" 21 | # https://ruby-doc.org/core-2.7.1/Regexp.html#class-Regexp-label-Subexpression+Calls 22 | rule_map["11"] = "(?[42]\\g?[31])" 23 | 24 | while rule_map[?0] =~ /\d/ 25 | zero = rule_map[?0] 26 | rule = zero.scan(/\d+/)[0] 27 | zero.gsub!(/\[#{rule}\]/, rule_map[rule]) 28 | end 29 | 30 | rule_map[?0].gsub!(/\s/, '') 31 | regex = Regexp.new("^#{rule_map[?0]}$") 32 | 33 | puts msgs.split("\n").count { |msg| regex.match(msg) } 34 | 35 | -------------------------------------------------------------------------------- /2020/day-22/day-22-input.txt: -------------------------------------------------------------------------------- 1 | Player 1: 2 | 50 3 | 14 4 | 10 5 | 17 6 | 38 7 | 40 8 | 3 9 | 46 10 | 39 11 | 25 12 | 18 13 | 2 14 | 41 15 | 45 16 | 7 17 | 47 18 | 36 19 | 1 20 | 30 21 | 32 22 | 8 23 | 31 24 | 12 25 | 5 26 | 28 27 | 28 | Player 2: 29 | 9 30 | 6 31 | 37 32 | 42 33 | 22 34 | 4 35 | 21 36 | 15 37 | 44 38 | 16 39 | 29 40 | 43 41 | 19 42 | 11 43 | 13 44 | 24 45 | 48 46 | 35 47 | 26 48 | 23 49 | 27 50 | 33 51 | 20 52 | 49 53 | 34 54 | 55 | -------------------------------------------------------------------------------- /2020/day-22/day-22-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-22-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | one = input.match(/1:\s((\d+\s)+)/).captures.first.split.map(&:to_i) 7 | two = input.match(/2:\s((\d+\s)+)/).captures.first.split.map(&:to_i) 8 | 9 | while one.any? && two.any? 10 | o = one.shift 11 | t = two.shift 12 | 13 | if o > t 14 | one << o 15 | one << t 16 | else 17 | two << t 18 | two << o 19 | end 20 | end 21 | 22 | winner = one.any? ? one : two 23 | 24 | puts winner.reverse.map.with_index { |num, idx| num * (idx + 1) }.sum 25 | 26 | -------------------------------------------------------------------------------- /2020/day-23/day-23-input.txt: -------------------------------------------------------------------------------- 1 | 871369452 2 | -------------------------------------------------------------------------------- /2020/day-23/day-23-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Solution not efficient enought for part 2, see part 2 for better solution 4 | 5 | file_path = File.expand_path("../day-23-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | cups = input.strip.chars.map(&:to_i) 9 | 10 | current = cups.first 11 | 12 | cups = cups.rotate(1) 13 | 14 | 100.times do 15 | slice = cups.take(3) 16 | cups = cups.drop(3) 17 | 18 | dest = current 19 | while 20 | dest = (dest - 2) % cups.size + 1 21 | break unless slice.include?(dest) 22 | end 23 | 24 | idx = cups.index(dest) 25 | cups = cups.rotate(idx + 1) 26 | 27 | cups = slice + cups 28 | 29 | current_index = (cups.index(current) + 1) % cups.size 30 | current = cups[current_index] 31 | cups = cups.rotate(current_index + 1) 32 | end 33 | 34 | puts cups.rotate(cups.index(1) + 1).join[0..-2] 35 | -------------------------------------------------------------------------------- /2020/day-25/day-25-input.txt: -------------------------------------------------------------------------------- 1 | 14082811 2 | 5249543 3 | -------------------------------------------------------------------------------- /2020/day-25/day-25-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-25-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | card, door = input.split("\n").map(&:to_i) 7 | 8 | def transform(value: 1, subject:, frequency: 1) 9 | frequency.times do 10 | value *= subject 11 | value %= 20201227 12 | end 13 | value 14 | end 15 | 16 | def identify_loop(subject) 17 | size = 0 18 | value = 1 19 | while value != subject 20 | value = transform(value: value, subject: 7) 21 | size += 1 22 | end 23 | 24 | size 25 | end 26 | 27 | loop1 = identify_loop(card) 28 | loop2 = identify_loop(door) 29 | 30 | puts transform(subject: door, frequency: loop1) 31 | puts transform(subject: card, frequency: loop2) 32 | -------------------------------------------------------------------------------- /2021/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | depths = input.split("\n").map(&:to_i) 7 | 8 | puts depths.each_cons(2).count { |a, b| b > a } 9 | -------------------------------------------------------------------------------- /2021/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | depths = input.split("\n").map(&:to_i) 7 | 8 | puts depths.each_cons(4).count do |a, b, c, d| 9 | (b + c + d) > (a + b + c) 10 | end 11 | -------------------------------------------------------------------------------- /2021/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | cmds = input.split("\n") 7 | 8 | depth = 0 9 | horizontal = 0 10 | 11 | cmds.each do |cmd| 12 | dir, num = cmd.split 13 | 14 | num = num.to_i 15 | 16 | case dir 17 | when "forward" 18 | horizontal += num 19 | when "up" 20 | depth -= num 21 | when "down" 22 | depth += num 23 | end 24 | end 25 | 26 | puts depth * horizontal 27 | -------------------------------------------------------------------------------- /2021/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | cmds = input.split("\n") 7 | 8 | depth = 0 9 | horizontal = 0 10 | aim = 0 11 | 12 | cmds.each do |cmd| 13 | dir, num = cmd.split 14 | 15 | num = num.to_i 16 | 17 | case dir 18 | when "forward" 19 | horizontal += num 20 | depth += aim * num 21 | when "up" 22 | aim -= num 23 | when "down" 24 | aim += num 25 | end 26 | end 27 | 28 | puts depth * horizontal 29 | -------------------------------------------------------------------------------- /2021/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | numbers = input.split("\n") 7 | 8 | gamma = numbers.map(&:chars).transpose.map do |bits| 9 | count = bits.select.count { |bit| bit == "0" } 10 | 11 | if count > bits.size / 2 12 | "0" 13 | else 14 | "1" 15 | end 16 | end 17 | 18 | gamma = gamma.join.to_i(2) 19 | epsilon = gamma ^ (2**12 - 1) 20 | 21 | puts gamma * epsilon 22 | 23 | -------------------------------------------------------------------------------- /2021/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | numbers = input.split("\n") 7 | 8 | o2 = numbers.map(&:chars) 9 | 10 | o2[0].size.times do |idx| 11 | max_bit = "1" 12 | 13 | count = o2.count { |o| o[idx] == "0" } 14 | 15 | if count > o2.size / 2.0 16 | max_bit = "0" 17 | end 18 | 19 | o2.select! { |o| o[idx] == max_bit } 20 | 21 | break if o2.count == 1 22 | end 23 | 24 | o2_rating = o2.join.to_i(2) 25 | 26 | 27 | co2 = numbers.map(&:chars) 28 | 29 | co2[0].size.times do |idx| 30 | max_bit = "0" 31 | 32 | count = co2.count { |co| co[idx] == "1" } 33 | 34 | if count < co2.size / 2.0 35 | max_bit = "1" 36 | end 37 | 38 | co2.select! { |co| co[idx] == max_bit } 39 | 40 | break if co2.count == 1 41 | end 42 | 43 | co2_rating = co2.join.to_i(2) 44 | 45 | puts co2_rating * o2_rating 46 | -------------------------------------------------------------------------------- /2021/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lines = [] 7 | 8 | input.split("\n").each do |line| 9 | lines << line.split(/,| -> /).map(&:to_i) 10 | end 11 | 12 | size = lines.flatten.max + 1 13 | 14 | grid = Array.new(size) { Array.new(size, 0) } 15 | 16 | lines.each do |(x1, y1, x2, y2)| 17 | y2, y1 = y1, y2 if y2 < y1 18 | x2, x1 = x1, x2 if x2 < x1 19 | 20 | if x1 == x2 21 | (y1..y2).each do |y| 22 | grid[y][x1] += 1 23 | end 24 | elsif y1 == y2 25 | (x1..x2).each do |x| 26 | grid[y1][x] += 1 27 | end 28 | end 29 | end 30 | 31 | puts grid.flatten.count { |x| x >= 2 } 32 | -------------------------------------------------------------------------------- /2021/day-05/day-05-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | lines = [] 7 | 8 | input.split("\n").each do |line| 9 | lines << line.split(/,| -> /).map(&:to_i) 10 | end 11 | 12 | size = lines.flatten.max + 1 13 | 14 | grid = Array.new(size) { Array.new(size, 0) } 15 | 16 | lines.each do |(x1, y1, x2, y2)| 17 | xd = 1 18 | yd = 1 19 | 20 | xd = -1 if x1 > x2 21 | yd = -1 if y1 > y2 22 | 23 | xd = 0 if x1 == x2 24 | yd = 0 if y1 == y2 25 | 26 | length = [(x1 - x2).abs, (y1 - y2).abs].max + 1 27 | 28 | length.times do |idx| 29 | grid[y1 + idx * yd][x1 + idx * xd] += 1 30 | end 31 | end 32 | 33 | puts grid.flatten.count { |x| x >= 2 } 34 | -------------------------------------------------------------------------------- /2021/day-06/day-06-input.txt: -------------------------------------------------------------------------------- 1 | 3,1,4,2,1,1,1,1,1,1,1,4,1,4,1,2,1,1,2,1,3,4,5,1,1,4,1,3,3,1,1,1,1,3,3,1,3,3,1,5,5,1,1,3,1,1,2,1,1,1,3,1,4,3,2,1,4,3,3,1,1,1,1,5,1,4,1,1,1,4,1,4,4,1,5,1,1,4,5,1,1,2,1,1,1,4,1,2,1,1,1,1,1,1,5,1,3,1,1,4,4,1,1,5,1,2,1,1,1,1,5,1,3,1,1,1,2,2,1,4,1,3,1,4,1,2,1,1,1,1,1,3,2,5,4,4,1,3,2,1,4,1,3,1,1,1,2,1,1,5,1,2,1,1,1,2,1,4,3,1,1,1,4,1,1,1,1,1,2,2,1,1,5,1,1,3,1,2,5,5,1,4,1,1,1,1,1,2,1,1,1,1,4,5,1,1,1,1,1,1,1,1,1,3,4,4,1,1,4,1,3,4,1,5,4,2,5,1,2,1,1,1,1,1,1,4,3,2,1,1,3,2,5,2,5,5,1,3,1,2,1,1,1,1,1,1,1,1,1,3,1,1,1,3,1,4,1,4,2,1,3,4,1,1,1,2,3,1,1,1,4,1,2,5,1,2,1,5,1,1,2,1,2,1,1,1,1,4,3,4,1,5,5,4,1,1,5,2,1,3 2 | -------------------------------------------------------------------------------- /2021/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | fishes = input.split(",").map(&:to_i).sort.tally 7 | 8 | fishes.default = 0 9 | 10 | 80.times do 11 | fishes.transform_keys! { |k| k - 1 } 12 | 13 | fishes[6] += fishes[-1] 14 | fishes[8] = fishes[-1] 15 | 16 | fishes[-1] = 0 17 | end 18 | 19 | puts fishes.values.inject(&:+) 20 | -------------------------------------------------------------------------------- /2021/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | fishes = input.split(",").map(&:to_i).sort.tally 7 | 8 | fishes.default = 0 9 | 10 | 256.times do 11 | fishes.transform_keys! { |k| k - 1 } 12 | 13 | fishes[6] += fishes[-1] 14 | fishes[8] = fishes[-1] 15 | 16 | fishes[-1] = 0 17 | end 18 | 19 | puts fishes.values.inject(&:+) 20 | -------------------------------------------------------------------------------- /2021/day-07/day-07-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | positions = input.split(",").map(&:to_i) 7 | 8 | min, max = positions.minmax 9 | 10 | fuel_totals = Array.new(max + 1, 0) 11 | 12 | positions.each do |pos| 13 | (min..max).each do |x| 14 | fuel_totals[x] += (pos - x).abs 15 | end 16 | end 17 | 18 | puts fuel_totals.min 19 | -------------------------------------------------------------------------------- /2021/day-07/day-07-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | positions = input.split(",").map(&:to_i) 7 | 8 | min, max = positions.minmax 9 | 10 | fuel_totals = Array.new(max + 1, 0) 11 | 12 | positions.each do |pos| 13 | fuel = 0 14 | 15 | (pos..max).each_with_index do |x, idx| 16 | fuel += idx 17 | fuel_totals[x] += fuel 18 | end 19 | 20 | fuel = 0 21 | 22 | (min..pos).each_with_index do |x, idx| 23 | fuel += idx 24 | fuel_totals[pos-x] += fuel 25 | end 26 | end 27 | 28 | puts fuel_totals.min 29 | -------------------------------------------------------------------------------- /2021/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n") 7 | .map { |line| line.split("|").last } 8 | .flat_map(&:split) 9 | .count { |x| [2, 3, 4, 7].include?(x.length) } 10 | -------------------------------------------------------------------------------- /2021/day-09/day-09-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | grid = input.split("\n").map { |line| line.split("").map(&:to_i) } 7 | 8 | width = grid[0].length 9 | height = grid.length 10 | 11 | risk = 0 12 | 13 | grid.each_with_index do |row, y| 14 | row.each_with_index do |cell, x| 15 | neighbours = [ 16 | [x - 1, y], 17 | [x + 1, y], 18 | [x, y + 1], 19 | [x, y - 1] 20 | ] 21 | 22 | neighbours.select! do |x1, y1| 23 | x1 >= 0 && x1 < width && 24 | y1 >= 0 && y1 < height 25 | end 26 | 27 | if neighbours.all? { |x1, y1| grid[y1][x1] > cell } 28 | risk += cell + 1 29 | end 30 | end 31 | end 32 | 33 | puts risk 34 | -------------------------------------------------------------------------------- /2021/day-10/day-10-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | CHARS = { 7 | '(' => ')', 8 | '{' => '}', 9 | '[' => ']', 10 | '<' => '>' 11 | } 12 | 13 | POINTS = { 14 | ')' => 3, 15 | ']' => 57, 16 | '}' => 1197, 17 | '>' => 25137 18 | } 19 | 20 | points = 0 21 | 22 | input.split("\n").map do |line| 23 | expectations = [] 24 | 25 | line.chars.each do |char| 26 | if CHARS.include?(char) 27 | expectations << CHARS[char] 28 | elsif expectations.last == char 29 | expectations.pop 30 | else 31 | points += POINTS[char] 32 | break 33 | end 34 | end 35 | end 36 | 37 | puts points 38 | -------------------------------------------------------------------------------- /2021/day-10/day-10-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | CHARS = { 7 | '(' => ')', 8 | '{' => '}', 9 | '[' => ']', 10 | '<' => '>' 11 | } 12 | 13 | POINTS = { 14 | ')' => 1, 15 | ']' => 2, 16 | '}' => 3, 17 | '>' => 4 18 | } 19 | 20 | points = [] 21 | 22 | input.split("\n").map do |line| 23 | expectations = [] 24 | 25 | line.chars.each do |char| 26 | if CHARS.include?(char) 27 | expectations << CHARS[char] 28 | elsif expectations.last == char 29 | expectations.pop 30 | else 31 | expectations.clear 32 | break 33 | end 34 | end 35 | 36 | # Skip if corrupt 37 | next if expectations.empty? 38 | 39 | score = 0 40 | expectations.reverse.each do |char| 41 | score *= 5 42 | score += POINTS[char] 43 | end 44 | 45 | points << score 46 | end 47 | 48 | puts points.sort[points.size / 2] 49 | -------------------------------------------------------------------------------- /2021/day-11/day-11-input.txt: -------------------------------------------------------------------------------- 1 | 4438624262 2 | 6263251864 3 | 2618812434 4 | 2134264565 5 | 1815131247 6 | 2612457325 7 | 8585767584 8 | 7217134556 9 | 2825456563 10 | 8248473584 11 | -------------------------------------------------------------------------------- /2021/day-12/day-12-input.txt: -------------------------------------------------------------------------------- 1 | EG-bj 2 | LN-end 3 | bj-LN 4 | yv-start 5 | iw-ch 6 | ch-LN 7 | EG-bn 8 | OF-iw 9 | LN-yv 10 | iw-TQ 11 | iw-start 12 | TQ-ch 13 | EG-end 14 | bj-OF 15 | OF-end 16 | TQ-start 17 | TQ-bj 18 | iw-LN 19 | EG-ch 20 | yv-iw 21 | KW-bj 22 | OF-ch 23 | bj-ch 24 | yv-TQ 25 | -------------------------------------------------------------------------------- /2021/day-12/day-12-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | caves = Hash.new { |h, k| h[k] = [] } 7 | 8 | input.split("\n").each do |line| 9 | from, to = line.split("-") 10 | 11 | from_cave = caves[from] 12 | to_cave = caves[to] 13 | 14 | from_cave << to unless "start" == to || "end" == from 15 | to_cave << from unless "start" == from || "end" == to 16 | end 17 | 18 | count = 0 19 | queue = [["start"]] 20 | 21 | while queue.any? 22 | path = queue.shift 23 | 24 | caves[path.last].each do |neighbour| 25 | next if neighbour.upcase != neighbour && path.include?(neighbour) 26 | 27 | count += 1 if neighbour == "end" 28 | 29 | new_path = path + [neighbour] 30 | 31 | queue << new_path 32 | end 33 | end 34 | 35 | puts count 36 | -------------------------------------------------------------------------------- /2021/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | polymer, insertion_rules = input.split("\n\n") 7 | 8 | rules = {} 9 | 10 | insertion_rules.split("\n").map do |rule| 11 | from, insert = rule.split(" -> ") 12 | 13 | rules[from] = insert 14 | end 15 | 16 | 10.times do 17 | new_polymer = polymer.chars.each_cons(2).map do |pair| 18 | pair = pair.join 19 | 20 | if rules[pair] 21 | pair[0] + rules[pair] 22 | else 23 | pair[0] 24 | end 25 | end 26 | 27 | new_polymer << polymer.chars.last 28 | 29 | polymer = new_polymer.join 30 | end 31 | 32 | puts polymer.chars.tally.values.minmax.inject(&:-).abs 33 | -------------------------------------------------------------------------------- /2021/day-16/day-16-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-16-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | packet = input.hex.to_s(2) 7 | .rjust(input.strip.size * 4, "0") 8 | .chars.map(&:to_i) 9 | 10 | def read_packet(packet) 11 | version = packet.shift(3).join.to_i(2) 12 | type = packet.shift(3).join.to_i(2) 13 | 14 | subpackets = [] 15 | 16 | case type 17 | when 4 18 | while packet.shift(5)[0] != 0 19 | end 20 | else 21 | if packet.shift == 0 22 | subpacket_length = packet.shift(15).join.to_i(2) 23 | 24 | subpacket = packet.shift(subpacket_length) 25 | 26 | while subpacket.length > 0 27 | version += read_packet(subpacket) 28 | end 29 | else 30 | num_subpackets = packet.shift(11).join.to_i(2) 31 | 32 | num_subpackets.times do 33 | version += read_packet(packet) 34 | end 35 | end 36 | end 37 | 38 | version 39 | end 40 | 41 | puts read_packet(packet) 42 | -------------------------------------------------------------------------------- /2021/day-17/day-17-input.txt: -------------------------------------------------------------------------------- 1 | target area: x=119..176, y=-141..-84 2 | -------------------------------------------------------------------------------- /2021/day-17/day-17-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-17-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | x1, x2, y1, y2 = input.scan(/x=([-\d]*)..([-\d]*), y=([-\d]*)..([-\d]*)/) 7 | .flatten.map(&:to_i) 8 | 9 | max_v = nil 10 | 11 | (y1..500).each do |yv| 12 | vel = yv 13 | current = yv 14 | step = 1 15 | 16 | while true 17 | if (y1..y2).cover?(current) 18 | max_v = yv 19 | break 20 | end 21 | 22 | vel -= 1 23 | current += vel 24 | step += 1 25 | 26 | break if current < y1 27 | end 28 | end 29 | 30 | vel = max_v 31 | 32 | max_y = 0 33 | 34 | while vel > 0 35 | max_y += vel 36 | vel -= 1 37 | end 38 | 39 | puts max_y 40 | -------------------------------------------------------------------------------- /2022/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n\n") 7 | .map{ |calories| calories.split.map(&:to_i).sum } 8 | .max 9 | -------------------------------------------------------------------------------- /2022/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n\n") 7 | .map{ |calories| calories.split.map(&:to_i).sum } 8 | .sort 9 | .last(3) 10 | .sum 11 | -------------------------------------------------------------------------------- /2022/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | scores = input.each_line.map { |line| 7 | opp, you = line.split 8 | 9 | opp = %w(A B C).index(opp) 10 | you = %w(X Y Z).index(you) 11 | 12 | score = you + 1 13 | if opp == you 14 | score += 3 # draw 15 | elsif (opp + 1) % 3 == you 16 | score += 6 # win 17 | end 18 | 19 | score 20 | } 21 | 22 | puts scores.sum 23 | -------------------------------------------------------------------------------- /2022/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | scores = input.each_line.map { |line| 7 | opp, you = line.split 8 | 9 | opp = %w(A B C).index(opp) 10 | 11 | case you 12 | when "X" # lose 13 | score = 1 + (opp - 1) % 3 14 | when "Y" # draw 15 | score = 1 + opp + 3 16 | when "Z" # win 17 | score = 1 + (opp + 1) % 3 + 6 18 | end 19 | } 20 | 21 | puts scores.sum 22 | -------------------------------------------------------------------------------- /2022/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | priorities = input.each_line.map { |runsack| 7 | compartments = runsack.strip.chars.each_slice(runsack.length / 2).to_a 8 | error = (compartments[0] & compartments[1]).first 9 | 10 | priority = error.downcase != error ? 26 : 0 11 | priority += error.downcase.ord - 'a'.ord + 1 12 | } 13 | 14 | puts priorities.sum 15 | -------------------------------------------------------------------------------- /2022/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | priorities = input.each_line.each_slice(3).map { |group| 7 | error = group.map(&:strip).map(&:chars).inject(:&).first 8 | 9 | priority = error.downcase != error ? 26 : 0 10 | priority += error.downcase.ord - 'a'.ord + 1 11 | } 12 | 13 | puts priorities.sum 14 | -------------------------------------------------------------------------------- /2022/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.each_line.count { |pair| 7 | pair = pair.strip.split(',') 8 | .map { |section| section.split('-').map(&:to_i) } 9 | .map { |section| Range.new(*section) } 10 | 11 | pair[0].cover?(pair[1]) || pair[1].cover?(pair[0]) 12 | } 13 | -------------------------------------------------------------------------------- /2022/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.each_line.count { |pair| 7 | pair = pair.strip.split(',') 8 | .map { |section| section.split('-').map(&:to_i) } 9 | .map { |section| Range.new(*section) } 10 | 11 | pair[0].cover?(pair[1].begin) || pair[0].cover?(pair[1].end) || 12 | pair[1].cover?(pair[0].begin) || pair[1].cover?(pair[0].end) 13 | } 14 | -------------------------------------------------------------------------------- /2022/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | stacks, instructions = input.split("\n\n") 7 | 8 | stacks = stacks.split("\n") 9 | num_stacks = stacks.pop.split.last.to_i 10 | 11 | rows = stacks.map { |row| 12 | row = row.chars.each_slice(4).map { |col| col.join.scan(/\w/).first } 13 | 14 | (num_stacks - row.length).times { row << nil } 15 | 16 | row 17 | } 18 | 19 | stacks = rows.transpose.map(&:compact) 20 | 21 | instructions.each_line do |instruction| 22 | count, from, to = instruction.scan(/(\d+).*(\d+).*(\d+)/)[0].map(&:to_i) 23 | 24 | stacks[to -1].unshift( 25 | *stacks[from - 1].shift(count).reverse 26 | ) 27 | end 28 | 29 | puts stacks.map(&:first).join 30 | -------------------------------------------------------------------------------- /2022/day-05/day-05-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | stacks, instructions = input.split("\n\n") 7 | 8 | stacks = stacks.split("\n") 9 | num_stacks = stacks.pop.split.last.to_i 10 | 11 | rows = stacks.map { |row| 12 | row = row.chars.each_slice(4).map { |col| col.join.scan(/\w/).first } 13 | 14 | (num_stacks - row.length).times { row << nil } 15 | 16 | row 17 | } 18 | 19 | stacks = rows.transpose.map(&:compact) 20 | 21 | instructions.each_line do |instruction| 22 | count, from, to = instruction.scan(/(\d+).*(\d+).*(\d+)/)[0].map(&:to_i) 23 | 24 | stacks[to -1].unshift( 25 | *stacks[from - 1].shift(count) 26 | ) 27 | end 28 | 29 | puts stacks.map(&:first).join 30 | -------------------------------------------------------------------------------- /2022/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | _, idx = input.chars.each_cons(4).with_index.find { |seq, idx| 7 | seq.uniq.count == 4 8 | } 9 | 10 | puts idx + 4 11 | -------------------------------------------------------------------------------- /2022/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | _, idx = input.chars.each_cons(14).with_index.find { |seq, idx| 7 | seq.uniq.count == 14 8 | } 9 | 10 | puts idx + 14 11 | -------------------------------------------------------------------------------- /2022/day-07/day-07-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | directories = Hash.new { |h, k| h[k] = [] } 7 | 8 | current_dir = [] 9 | 10 | input.each_line do |line| 11 | case line.split 12 | in [/\d+/ => size, _file] 13 | directories[current_dir.clone] << size.to_i 14 | in ["dir", /\w+/ => dir] 15 | new_dir = current_dir.clone.append(dir) 16 | directories[current_dir.clone] << directories[new_dir] 17 | in ["$", "cd", ".."] 18 | current_dir.pop 19 | in ["$", "cd", /.+/ => dir] 20 | current_dir << dir 21 | else # ls 22 | end 23 | end 24 | 25 | puts directories.map { |_k, v| v.flatten.sum } 26 | .select { |size| size <= 100_000 } 27 | .sum 28 | -------------------------------------------------------------------------------- /2022/day-07/day-07-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | directories = Hash.new { |h, k| h[k] = [] } 7 | 8 | current_dir = [] 9 | 10 | input.each_line do |line| 11 | case line.split 12 | in [/\d+/ => size, _file] 13 | directories[current_dir.clone] << size.to_i 14 | in ["dir", /\w+/ => dir] 15 | new_dir = current_dir.clone.append(dir) 16 | directories[current_dir.clone] << directories[new_dir] 17 | in ["$", "cd", ".."] 18 | current_dir.pop 19 | in ["$", "cd", /.+/ => dir] 20 | current_dir << dir 21 | else # ls 22 | end 23 | end 24 | 25 | total_space = 70_000_000 26 | target_free_space = 30_000_000 27 | used_space = directories[["/"]].flatten.sum 28 | minimum_to_delete = target_free_space - (total_space - used_space) 29 | 30 | puts directories.map { |_k, v| v.flatten.sum } 31 | .select { |size| size >= minimum_to_delete } 32 | .min 33 | -------------------------------------------------------------------------------- /2022/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | grid = input.each_line.map { |line| line.strip.chars.map(&:to_i) } 9 | 10 | trees = Set.new 11 | 12 | max = -1 13 | proc = Proc.new do |height, x, y| 14 | next if height <= max 15 | trees << [y, x] 16 | max = height 17 | end 18 | 19 | grid.each_with_index do |row, y| 20 | max = -1 21 | row.each_with_index do |height, x| 22 | proc.call(height, x, y) 23 | end 24 | 25 | max = -1 26 | row.each_with_index.reverse_each do |height, x| 27 | proc.call(height, x, y) 28 | end 29 | end 30 | 31 | grid.transpose.each_with_index do |col, x| 32 | max = -1 33 | col.each_with_index do |height, y| 34 | proc.call(height, x, y) 35 | end 36 | 37 | max = -1 38 | col.each_with_index.reverse_each do |height, y| 39 | proc.call(height, x, y) 40 | end 41 | end 42 | 43 | puts trees.count 44 | -------------------------------------------------------------------------------- /2022/day-09/day-09-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | hx = hy = 0 9 | tx = ty = 0 10 | 11 | visited = [[tx, ty]].to_set 12 | 13 | input.each_line do |line| 14 | dir, v = line.split 15 | v = v.to_i 16 | 17 | v.times do 18 | case dir 19 | when "R" 20 | hx += 1 21 | when "L" 22 | hx -= 1 23 | when "U" 24 | hy += 1 25 | when "D" 26 | hy -= 1 27 | end 28 | 29 | # neighbour check 30 | next if (hx - tx).abs <= 1 && (hy - ty).abs <= 1 31 | 32 | if hy != ty 33 | ty += (hy - ty).positive? ? 1 : -1 34 | end 35 | 36 | if hx != tx 37 | tx += (hx - tx).positive? ? 1 : -1 38 | end 39 | 40 | visited << [tx, ty] 41 | end 42 | end 43 | 44 | puts visited.count 45 | -------------------------------------------------------------------------------- /2022/day-10/day-10-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | class Cpu 7 | attr_reader :x, :cycle, :signal_sum 8 | 9 | def initialize 10 | @x = 1 11 | @cycle = 0 12 | @signal_sum = 0 13 | end 14 | 15 | def tick 16 | @cycle += 1 17 | 18 | if (cycle - 20) % 40 == 0 19 | @signal_sum += cycle * x 20 | end 21 | end 22 | 23 | def add(i) 24 | @x += i 25 | end 26 | end 27 | 28 | cpu = Cpu.new 29 | 30 | input.each_line do |line| 31 | case line.strip.split 32 | in ["addx", add] 33 | cpu.tick 34 | cpu.tick 35 | cpu.add(add.to_i) 36 | in ["noop"] 37 | cpu.tick 38 | end 39 | end 40 | 41 | puts cpu.signal_sum 42 | 43 | -------------------------------------------------------------------------------- /2022/day-10/day-10-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | class Cpu 7 | attr_reader :x, :cycle 8 | 9 | def initialize 10 | @x = 1 11 | @cycle = 0 12 | end 13 | 14 | def tick 15 | @cycle += 1 16 | 17 | draw 18 | end 19 | 20 | def add(i) 21 | @x += i 22 | end 23 | 24 | private 25 | 26 | def draw 27 | print lit_pixel? ? "#" : "." 28 | 29 | puts if cycle % 40 == 0 30 | end 31 | 32 | def lit_pixel? 33 | pixel = cycle % 40 34 | 35 | pixel >= x && pixel < x + 3 36 | end 37 | end 38 | 39 | cpu = Cpu.new 40 | 41 | input.each_line do |line| 42 | case line.strip.split 43 | in ["addx", add] 44 | cpu.tick 45 | cpu.tick 46 | cpu.add(add.to_i) 47 | in ["noop"] 48 | cpu.tick 49 | end 50 | end 51 | 52 | -------------------------------------------------------------------------------- /2022/day-12/day-12-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-12-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | grid = input.split("\n").map(&:chars) 7 | 8 | y = grid.find_index { |row| row.include?("S") } 9 | x = grid[y].find_index { |cell| cell == "S" } 10 | 11 | visited = {} 12 | 13 | queue = [[x, y, 0, ?a]] 14 | 15 | def neighbours(x, y) 16 | [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]].select do |x, y| 17 | x >= 0 && y >= 0 18 | end 19 | end 20 | 21 | while queue.any? 22 | x, y, d, h = queue.shift 23 | 24 | neighbours(x, y).each do |x1, y1| 25 | h1 = grid[y1]&.[](x1) 26 | 27 | next unless h1 28 | next if h1 > h.next 29 | 30 | d1 = d + 1 31 | 32 | if h1 == 'E' 33 | puts d1 34 | exit 35 | elsif !visited[[x1, y1]] 36 | queue << [x1, y1, d1, h1] 37 | visited[[x1, y1]] = d1 38 | else 39 | d2 = visited[[x1, y1]] 40 | visited[[x1, y1]] = [d1, d2].min 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /2022/day-13/day-13-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'json' 4 | 5 | file_path = File.expand_path("../day-13-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | def compare(l1, l2) 9 | return 0 if l1 == l2 10 | 11 | l1.each_with_index do |i1, idx| 12 | i2 = l2[idx] 13 | 14 | return 1 if i2.nil? 15 | 16 | next if i1 == i2 17 | 18 | if i1.is_a?(Integer) && i2.is_a?(Integer) 19 | return i1 <=> i2 20 | else 21 | i1 = [i1] if i1.is_a?(Integer) 22 | i2 = [i2] if i2.is_a?(Integer) 23 | 24 | next if i1 == i2 25 | return compare(i1, i2) 26 | end 27 | end 28 | 29 | -1 30 | end 31 | 32 | sum = 0 33 | 34 | input.split("\n\n").each_with_index do |pair, idx| 35 | p1, p2 = pair.split("\n") 36 | 37 | p1 = JSON.parse(p1) 38 | p2 = JSON.parse(p2) 39 | 40 | sum += idx + 1 if compare(p1, p2) <= 0 41 | end 42 | 43 | puts sum 44 | -------------------------------------------------------------------------------- /2022/day-13/day-13-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'json' 4 | 5 | file_path = File.expand_path("../day-13-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | def compare(l1, l2) 9 | return 0 if l1 == l2 10 | 11 | l1.each_with_index do |i1, idx| 12 | i2 = l2[idx] 13 | 14 | return 1 if i2.nil? 15 | 16 | next if i1 == i2 17 | 18 | if i1.is_a?(Integer) && i2.is_a?(Integer) 19 | return i1 <=> i2 20 | else 21 | i1 = [i1] if i1.is_a?(Integer) 22 | i2 = [i2] if i2.is_a?(Integer) 23 | 24 | next if i1 == i2 25 | return compare(i1, i2) 26 | end 27 | end 28 | 29 | -1 30 | end 31 | 32 | lists = input.scan(/\[.*/).map { |l| JSON.parse(l) } 33 | 34 | d1 = [[2]] 35 | d2 = [[6]] 36 | 37 | lists << d1 38 | lists << d2 39 | 40 | lists.sort! { |l1, l2| compare(l1, l2) } 41 | 42 | puts (lists.index(d1) + 1 ) * (lists.index(d2) + 1) 43 | -------------------------------------------------------------------------------- /2022/day-18/day-18-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-18-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | cubes = Set.new 9 | 10 | input.strip.split("\n").map do |cube| 11 | cubes << cube.split(",").map(&:to_i) 12 | end 13 | 14 | count = 0 15 | 16 | cubes.each do |pos| 17 | neighbours = [-1, 1].product([0, 1, 2]).map do |v, i| 18 | neighbour = pos.clone 19 | neighbour[i] += v 20 | 21 | count += 1 if cubes.include?(neighbour) 22 | end 23 | end 24 | 25 | puts cubes.count * 6 - count 26 | -------------------------------------------------------------------------------- /2022/day-20/day-20-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | nums = input.split.map(&:to_i) 7 | .each_with_index.map { [_1, _2] } 8 | 9 | nums.length.times { |n| 10 | idx = nums.index { _2 == n } 11 | 12 | val = nums.delete_at(idx) 13 | 14 | nums.insert((idx + val[0]) % nums.size, val) 15 | } 16 | 17 | idx = nums.index { _1[0] == 0 } 18 | 19 | puts nums[(idx + 1000) % nums.length][0] + 20 | nums[(idx + 2000) % nums.length][0] + 21 | nums[(idx + 3000) % nums.length][0] 22 | -------------------------------------------------------------------------------- /2022/day-20/day-20-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-20-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | nums = input.split.map(&:to_i) 7 | 8 | nums = nums.each_with_index.map { [_1 * 811589153, _2] } 9 | 10 | 10.times { 11 | nums.length.times { |n| 12 | idx = nums.find_index { _2 == n } 13 | 14 | val = nums.delete_at(idx) 15 | 16 | nums.insert((idx + val[0]) % nums.size, val) 17 | } 18 | } 19 | 20 | idx = nums.index { _1[0] == 0 } 21 | 22 | puts nums[(idx + 1000) % nums.length][0] + 23 | nums[(idx + 2000) % nums.length][0] + 24 | nums[(idx + 3000) % nums.length][0] 25 | -------------------------------------------------------------------------------- /2022/day-21/day-21-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-21-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | monkeys = input.split(?\n).map { 7 | out, ins = _1.split(": ") 8 | ins = ins.to_i if ins.match?(/\d+/) 9 | 10 | [out, ins] 11 | } 12 | 13 | solved, unsolved = monkeys 14 | .partition { _2.is_a?(Numeric) } 15 | .map(&:to_h) 16 | 17 | while unsolved.any? 18 | unsolved.each do |out, expression| 19 | a, op, b = expression.split 20 | next unless solved[a] && solved[b] 21 | 22 | solved[out] = solved[a].send(op, solved[b]) 23 | unsolved.delete(out) 24 | end 25 | end 26 | 27 | puts solved["root"] 28 | -------------------------------------------------------------------------------- /2023/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input 7 | .split("\n") 8 | .sum { _1.scan(/\d/).values_at(0, -1).join.to_i } 9 | .tap { puts _1 } 10 | -------------------------------------------------------------------------------- /2023/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | # We don't need a fany Hash here for the given input. We could 7 | # make do with an Array and call `DIGITS.index(match)&.+(1)` 8 | # instead of `DIGITS[match]` 9 | DIGITS = %w(one two three four five six seven eight nine) 10 | .map.with_index 11 | .to_a.to_h 12 | .transform_values { _1 + 1 } 13 | 14 | # Postive lookahead assertion regex 15 | input 16 | .split("\n") 17 | .sum { 18 | _1.scan(/(?=(#{DIGITS.keys.join("|")}|\d))/) 19 | .flatten 20 | .values_at(0, -1) 21 | .map { |match| DIGITS[match] || match } 22 | .join 23 | .to_i 24 | } 25 | .tap { puts _1 } 26 | -------------------------------------------------------------------------------- /2023/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | RED = 12 7 | GREEN = 13 8 | BLUE = 14 9 | 10 | input 11 | .each_line 12 | .sum { 13 | blue = _1.scan(/(\d+) b/).flatten.map(&:to_i).max 14 | red = _1.scan(/(\d+) r/).flatten.map(&:to_i).max 15 | green = _1.scan(/(\d+) g/).flatten.map(&:to_i).max 16 | 17 | if blue > BLUE || red > RED || green > GREEN 18 | 0 19 | else 20 | _1.scan(/Game (\d*)/).flatten.first.to_i 21 | end 22 | } 23 | .tap { puts _1 } 24 | -------------------------------------------------------------------------------- /2023/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input 7 | .each_line 8 | .sum { 9 | blue = _1.scan(/(\d+) b/).flatten.map(&:to_i).max 10 | red = _1.scan(/(\d+) r/).flatten.map(&:to_i).max 11 | green = _1.scan(/(\d+) g/).flatten.map(&:to_i).max 12 | 13 | blue * red * green 14 | } 15 | .tap { puts _1 } 16 | -------------------------------------------------------------------------------- /2023/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | numbers = {} 7 | 8 | lines = input.each_line.to_a.map(&:strip) 9 | 10 | lines.each_with_index do |line, y| 11 | line.scan(/\d+/) do 12 | numbers[[Regexp.last_match.begin(0), y]] = _1 13 | end 14 | end 15 | 16 | numbers.sum { |(x, y), num| 17 | min_x = [x - 1, 0].max 18 | min_y = [y - 1, 0].max 19 | 20 | max_x = x + num.length 21 | max_y = y + 1 22 | 23 | lines[min_y..max_y] 24 | .map { _1[min_x..max_x] } 25 | .join 26 | .match?(/[^\d\.]/) 27 | .then { _1 ? num.to_i : 0 } 28 | } 29 | .tap { puts _1 } 30 | 31 | -------------------------------------------------------------------------------- /2023/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | gears = {} 7 | numbers = {} 8 | 9 | input.each_line.with_index do |line, y| 10 | line.scan(/\*/) do 11 | gears[[Regexp.last_match.begin(0), y]] = [] 12 | end 13 | 14 | line.scan(/\d+/) do 15 | numbers[[Regexp.last_match.begin(0), y]] = _1 16 | end 17 | end 18 | 19 | numbers.each { |(x, y), num| 20 | min_x = x - 1 21 | min_y = y - 1 22 | 23 | max_x = x + num.length 24 | max_y = y + 1 25 | 26 | (min_x..max_x).to_a.product((min_y..max_y).to_a) 27 | .select { gears[_1] } 28 | .each { gears[_1] << num.to_i } 29 | } 30 | 31 | gears 32 | .values 33 | .select { _1.count == 2 } 34 | .sum { _1.reduce(:*) } 35 | .tap { puts _1 } 36 | -------------------------------------------------------------------------------- /2023/day-04/day-04-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.each_line.sum { 7 | _, winners, numbers = _1.split(/[:|]/) 8 | 9 | winners = winners.scan(/\d+/) 10 | numbers = numbers.scan(/\d+/) 11 | 12 | matches = (winners & numbers).count 13 | 14 | if matches > 0 15 | 2**(matches - 1) 16 | else 17 | 0 18 | end 19 | } 20 | .tap { puts _1 } 21 | -------------------------------------------------------------------------------- /2023/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input 7 | .each_line 8 | .with_object(Hash.new(0)) { |line, counts| 9 | id, winners, numbers = line.split(/[:|]/) 10 | 11 | id = id.scan(/\d+/).first.to_i 12 | winners = winners.scan(/\d+/) 13 | numbers = numbers.scan(/\d+/) 14 | 15 | matches = (winners & numbers).count 16 | 17 | counts[id] += 1 18 | 19 | matches.times do |i| 20 | card_id = id + i + 1 21 | counts[card_id] += counts[id] 22 | end 23 | } 24 | .values 25 | .sum 26 | .tap { puts _1 } 27 | -------------------------------------------------------------------------------- /2023/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | seeds, *maps = input.split("\n\n") 7 | 8 | seeds = seeds.scan(/\d+/).map(&:to_i) 9 | 10 | maps.map! { 11 | map = {} 12 | 13 | _1.split("\n")[1..-1].each do |line| 14 | dest, source, length = line.split.map(&:to_i) 15 | 16 | range = source..(source + length) 17 | offset = dest - source 18 | 19 | map[range] = offset 20 | end 21 | 22 | map 23 | } 24 | 25 | seeds 26 | .map { |source| 27 | maps.reduce(source) do |source, map| 28 | range, offset = map.find do |range, offset| 29 | range.include?(source) 30 | end 31 | 32 | source += offset if range 33 | source 34 | end 35 | } 36 | .min 37 | .tap { puts _1 } 38 | -------------------------------------------------------------------------------- /2023/day-06/day-06-input.txt: -------------------------------------------------------------------------------- 1 | Time: 35 69 68 87 2 | Distance: 213 1168 1086 1248 3 | -------------------------------------------------------------------------------- /2023/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | times, distances = input.split("\n") 7 | 8 | times = times.scan(/\d+/).map(&:to_i) 9 | distances = distances.scan(/\d+/).map(&:to_i) 10 | 11 | times.zip(distances) 12 | .map { |time, record| 13 | time.times.count { _1 * (time - _1) > record } 14 | } 15 | .inject(:*) 16 | .tap { puts _1 } 17 | -------------------------------------------------------------------------------- /2023/day-06/day-06-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | time, distance = input.split("\n") 7 | 8 | time = time.scan(/\d+/).join.to_i 9 | record = distance.scan(/\d+/).join.to_i 10 | 11 | time.times 12 | .count { _1 * (time - _1) > record } 13 | .tap { puts _1 } 14 | 15 | -------------------------------------------------------------------------------- /2023/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | steps, map = input.split("\n\n") 7 | 8 | steps = steps.chars 9 | 10 | network = {} 11 | 12 | map.each_line { 13 | from, *dest = _1.scan(/\w+/) 14 | network[from] = dest 15 | } 16 | 17 | i = 0 18 | curr = "AAA" 19 | 20 | while curr != "ZZZ" 21 | step = steps[i % (steps.length)] 22 | 23 | dir = step == ?L ? 0 : 1 24 | curr = network[curr][dir] 25 | 26 | i += 1 27 | end 28 | 29 | puts i 30 | -------------------------------------------------------------------------------- /2023/day-08/day-08-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | steps, map = input.split("\n\n") 7 | 8 | steps = steps.chars 9 | 10 | network = {} 11 | 12 | map.each_line { 13 | from, *dest = _1.scan(/\w+/) 14 | network[from] = dest 15 | } 16 | 17 | starts = network.keys.select { _1 =~ /A$/ } 18 | 19 | starts 20 | .map { |curr| 21 | i = 0 22 | 23 | while !curr.match?(/Z$/) 24 | step = steps[i % (steps.length)] 25 | 26 | dir = step == ?L ? 0 : 1 27 | curr = network[curr][dir] 28 | 29 | i += 1 30 | end 31 | 32 | i 33 | } 34 | .inject(:lcm) 35 | .tap { puts _1 } 36 | -------------------------------------------------------------------------------- /2023/day-09/day-09-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.each_line 7 | .sum { | line| 8 | i = line.split.map(&:to_i) 9 | 10 | seqs = [i] 11 | 12 | while !seqs.last.all?(&:zero?) 13 | seqs << seqs.last.each_cons(2).map { _2 - _1 } 14 | end 15 | 16 | seqs.reverse_each.with_index { |seq, idx| 17 | if idx.zero? 18 | seq << 0 19 | else 20 | seq << (seq.last + seqs[-idx].last) 21 | end 22 | } 23 | 24 | seqs.first.last 25 | } 26 | .tap { puts _1 } 27 | -------------------------------------------------------------------------------- /2023/day-09/day-09-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-09-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.each_line 7 | .sum { | line| 8 | i = line.split.map(&:to_i) 9 | 10 | seqs = [i] 11 | 12 | while !seqs.last.all?(&:zero?) 13 | seqs << seqs.last.each_cons(2).map { _2 - _1 } 14 | end 15 | 16 | seqs.reverse_each.with_index { |seq, idx| 17 | if idx.zero? 18 | seq.unshift(0) 19 | else 20 | seq.unshift(seq.first - seqs[-idx].first) 21 | end 22 | } 23 | 24 | seqs.first.first 25 | } 26 | .tap { puts _1 } 27 | -------------------------------------------------------------------------------- /2023/day-11/day-11-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | grid = input.each_line.map { _1.strip.chars } 7 | 8 | width = grid.first.count 9 | height = grid.count 10 | 11 | y_expand = height.times.select { 12 | grid[_1].join.match?(/\A\.*\z/) 13 | } 14 | 15 | transposed_grid = grid.transpose 16 | 17 | x_expand = width.times.select { 18 | transposed_grid[_1].join.match?(/\A\.*\z/) 19 | } 20 | 21 | height.times.to_a 22 | .product(width.times.to_a) 23 | .select { grid[_1][_2] == ?# } 24 | .map { [_2, _1] } 25 | .combination(2) 26 | .sum { |(x1, y1), (x2, y2)| 27 | x_range = Range.new(*[x1, x2].sort) 28 | y_range = Range.new(*[y1, y2].sort) 29 | 30 | x_range.size + y_range.size - 2 + 31 | 999_999 * x_expand.count { x_range.include?(_1) } + 32 | 999_999 * y_expand.count { y_range.include?(_1) } 33 | } 34 | .tap { puts _1 } 35 | -------------------------------------------------------------------------------- /2023/day-13/day-13-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-13-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | def row_count(grid) 7 | (grid.count - 1) 8 | .times 9 | .map { |y| 10 | left = grid[0..y].reverse 11 | right = grid[y+1..] 12 | 13 | left.count if left.zip(right).select(&:last).all? { _1 == _2 } 14 | } 15 | .compact 16 | .first 17 | end 18 | 19 | input 20 | .split("\n\n") 21 | .map { |pattern| 22 | grid = pattern.each_line.map(&:strip).map(&:chars) 23 | 24 | row_count(grid.transpose) || row_count(grid) * 100 25 | } 26 | .sum 27 | .tap { puts _1 } 28 | 29 | -------------------------------------------------------------------------------- /2023/day-13/day-13-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-13-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | def row_count(grid) 7 | (grid.count - 1) 8 | .times 9 | .map { |y| 10 | left = grid[0..y].reverse 11 | right = grid[y+1..] 12 | 13 | errors = left.zip(right).select(&:last).sum { |l, r| 14 | l.zip(r).count { _1 != _2 } 15 | } 16 | 17 | left.count if errors == 1 18 | } 19 | .compact 20 | .first 21 | end 22 | 23 | input 24 | .split("\n\n") 25 | .map { |pattern| 26 | grid = pattern.each_line.map(&:strip).map(&:chars) 27 | 28 | row_count(grid.transpose) || row_count(grid) * 100 29 | } 30 | .sum 31 | .tap { puts _1 } 32 | 33 | -------------------------------------------------------------------------------- /2023/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | grid = input.each_line.map { _1.strip.chars } 7 | 8 | # Tilt left 9 | def tilt(grid) 10 | grid.map do |row| 11 | row 12 | .join 13 | .split(?#) 14 | .map { |section| 15 | count = section.chars.count { _1 == ?O } 16 | 17 | ?O * count + ?. * (section.length - count) 18 | } 19 | .join(?#) 20 | .ljust(row.length, ?#) 21 | .chars 22 | end 23 | end 24 | 25 | grid 26 | .then { tilt(_1.transpose).transpose } 27 | .map { |row| row.count { _1 == ?O } } 28 | .each_with_index 29 | .sum { |count, idx| count * (grid.length - idx) } 30 | .tap { puts _1 } 31 | -------------------------------------------------------------------------------- /2023/day-15/day-15-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-15-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input 7 | .strip 8 | .split(",") 9 | .sum { 10 | _1.chars.inject(0) { |val, chr| 11 | val += chr.ord 12 | val *= 17 13 | val %= 256 14 | } 15 | } 16 | .tap { puts _1 } 17 | -------------------------------------------------------------------------------- /2023/day-15/day-15-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-15-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | boxes = Hash.new { |h, k| h[k] = [] } 7 | 8 | input 9 | .strip 10 | .split(",") 11 | .each { 12 | label = _1.scan(/\w*/).first 13 | 14 | bi = label.chars.inject(0) { |bi, chr| 15 | bi += chr.ord 16 | bi *= 17 17 | bi %= 256 18 | } 19 | 20 | box = boxes[bi] 21 | 22 | op, fl = _1.strip.chars[label.length..] 23 | fl = fl.to_i 24 | 25 | idx = box.index { |lab, _| lab == label } 26 | 27 | if op == ?- 28 | box.delete_at(idx) if idx 29 | elsif idx 30 | box[idx] = [label, fl] 31 | else 32 | box << [label, fl] 33 | end 34 | } 35 | 36 | boxes 37 | .sum { |box, lenses| 38 | lenses.each.with_index.sum { |(_, fl), idx| 39 | (box + 1) * (idx + 1) * fl 40 | } 41 | } 42 | .tap { puts _1 } 43 | -------------------------------------------------------------------------------- /2023/day-21/day-21-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-21-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | grid = input.each_line.map { _1.strip.chars } 7 | 8 | w = grid.first.count 9 | h = grid.count 10 | 11 | idx = grid.flatten.index(?S) 12 | 13 | y = idx / h 14 | x = idx % h 15 | 16 | queue = [[x, y, 0]] 17 | 18 | visited = {} 19 | visited[[x,y]] = 0 20 | 21 | while queue.any? 22 | x, y, step = queue.shift 23 | 24 | [[0, 1], [0, -1], [1, 0], [-1, 0]].each do |dir| 25 | x1, y1 = dir.zip([x,y]).map(&:sum) 26 | 27 | next if x1 < 0 || y1 < 0 || x1 >= w || y1 >= h 28 | 29 | c = grid[y1][x1] 30 | 31 | next if c == ?# 32 | next if visited[[x1, y1]] 33 | 34 | visited[[x1,y1]] = step + 1 35 | queue << [x1, y1, step + 1] 36 | end 37 | end 38 | 39 | visited.values 40 | .count { _1 <= 64 && _1.even? } 41 | .tap { pp _1 } 42 | -------------------------------------------------------------------------------- /2024/day-01/day-01-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split(/\s+/) 7 | .map(&:to_i) 8 | .each_slice(2) 9 | .to_a 10 | .transpose 11 | .map(&:sort) 12 | .transpose 13 | .map { _1.inject(&:-) } 14 | .map(&:abs) 15 | .sum 16 | -------------------------------------------------------------------------------- /2024/day-01/day-01-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-01-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | left, right = input.split(/\s+/) 7 | .map(&:to_i) 8 | .each_slice(2) 9 | .to_a 10 | .transpose 11 | .map(&:sort) 12 | .map(&:tally) 13 | 14 | right.default = 0 15 | 16 | puts left 17 | .map { |num, freq| num * freq * right[num] } 18 | .sum 19 | -------------------------------------------------------------------------------- /2024/day-02/day-02-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | puts input.split("\n") 7 | .map(&:split) 8 | .map { _1.map(&:to_i) } 9 | .map { 10 | _1 11 | .each_cons(2).to_a 12 | .map { |pair| pair.inject(:-) } 13 | } 14 | .select { _1.all?(&:positive?) || _1.all?(&:negative?) } 15 | .select { _1.map(&:abs).all? { |diff| diff <= 3 } } 16 | .count 17 | -------------------------------------------------------------------------------- /2024/day-02/day-02-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-02-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | reports = input.split("\n") 7 | .map(&:split) 8 | .map { _1.map(&:to_i) } 9 | 10 | def safe?(report, can_remove = false) 11 | increasing = report[0] < report[1] 12 | 13 | report.each_cons(2).with_index do |(a, b), idx| 14 | if increasing != a < b || a == b || (a - b).abs > 3 15 | return false if !can_remove 16 | 17 | return safe?(report.dup.tap { _1.delete_at(idx) }) || 18 | safe?(report.dup.tap { _1.delete_at(idx + 1) }) || 19 | safe?(report.dup.tap { _1.delete_at(idx - 1) }) 20 | end 21 | end 22 | 23 | true # for clarity 24 | end 25 | 26 | puts reports.count { safe?(_1, true) } 27 | -------------------------------------------------------------------------------- /2024/day-03/day-03-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | regex = / 7 | mul\( 8 | (\d+), 9 | (\d+) 10 | \) 11 | /x 12 | 13 | puts input.scan(regex) 14 | .flatten 15 | .map(&:to_i) 16 | .each_slice(2) 17 | .map { _1.inject(:*) } 18 | .sum 19 | -------------------------------------------------------------------------------- /2024/day-03/day-03-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-03-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | regex = / 7 | ( 8 | mul\( 9 | (\d+), 10 | (\d+) 11 | \) 12 | | 13 | do[n't]*\(\) 14 | ) 15 | /x 16 | 17 | sum = 0 18 | enabled = true 19 | 20 | input.scan(regex).each do |instruction, a, b| 21 | if instruction == "do()" 22 | enabled = true 23 | elsif instruction == "don't()" 24 | enabled = false 25 | end 26 | 27 | sum += a.to_i * b.to_i if enabled 28 | end 29 | 30 | puts sum 31 | -------------------------------------------------------------------------------- /2024/day-04/day-04-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-04-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | count = 0 7 | 8 | rows = input.split.map(&:chars) 9 | 10 | rows[0..-3].each.with_index do |row, y| 11 | row[0..-3].each.with_index do |_, x| 12 | next unless rows[y + 1][x + 1] == ?A 13 | 14 | next if rows[y][x, 3].rotate(-1)[0..1] 15 | .zip( 16 | rows[y + 2][x, 3].rotate(-1)[0..1].reverse 17 | ) 18 | .map(&:sort) 19 | .any? { _1 != [?M, ?S] } 20 | 21 | count += 1 22 | end 23 | end 24 | 25 | puts count 26 | -------------------------------------------------------------------------------- /2024/day-05/day-05-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-05-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | rules, updates = input.split("\n\n") 9 | 10 | rules_list = Hash.new { |h, k| h[k] = Set.new } 11 | 12 | rules.split 13 | .map { _1.split(?|).map(&:to_i) } 14 | .each { rules_list[_1].add(_2) } 15 | 16 | updates = updates.split 17 | .map { _1.split(?,).map(&:to_i) } 18 | 19 | updates 20 | .select { |pages| 21 | pages.each.with_index.all? do |page, idx| 22 | pages[(idx + 1)..].all? { !rules_list[_1].include?(page) } 23 | end 24 | } 25 | .map { _1[_1.length / 2] } 26 | .inject(:+) 27 | .tap { puts _1 } 28 | -------------------------------------------------------------------------------- /2024/day-06/day-06-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-06-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | grid = input.split.map(&:chars) 9 | 10 | width = grid[0].size 11 | height = grid.size 12 | 13 | loc = input.split.join.index(?^) 14 | 15 | x = loc % width 16 | y = loc / width 17 | 18 | dir = [0, -1] 19 | pos = [x, y] 20 | 21 | visited = Set.new([[x, y]]) 22 | 23 | while true 24 | next_pos = pos.zip(dir).map { _1.inject(:+) } 25 | x, y = next_pos 26 | 27 | break if x < 0 || x >= width || y < 0 || y >= height 28 | 29 | if grid[y] && grid[y][x] == ?# 30 | dir = [-dir[1], dir[0]] 31 | else 32 | pos = next_pos 33 | visited.add(pos) 34 | end 35 | end 36 | 37 | puts visited.count 38 | -------------------------------------------------------------------------------- /2024/day-07/day-07-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.split(?\n) 7 | .map(&:split) 8 | .map { _1.map(&:to_i) } 9 | .select { |target, *nums| 10 | operators = nums.size - 1 11 | 12 | (0..(2**operators - 1)).find { 13 | ops = _1.to_s(2).rjust(operators, ?0).tr("01", "*+").chars 14 | 15 | total = nums.first 16 | 17 | nums[1..].each.with_index { |num, idx| 18 | total = total.send(ops[idx], num) 19 | } 20 | 21 | total == target 22 | } 23 | } 24 | .map { _1.first } 25 | .sum 26 | .tap { puts _1 } 27 | -------------------------------------------------------------------------------- /2024/day-07/day-07-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-07-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.split(?\n) 7 | .map(&:split) 8 | .map { _1.map(&:to_i) } 9 | .select { |target, *nums| 10 | operators = nums.size - 1 11 | 12 | (0..(3**operators - 1)).find { 13 | ops = _1.to_s(3).rjust(operators, ?0).tr("012", "*+|").chars 14 | 15 | total = nums.first 16 | 17 | nums[1..].each.with_index { |num, idx| 18 | case ops[idx] 19 | when ?* 20 | total *= num 21 | when ?+ 22 | total += num 23 | when ?| 24 | total = (total.to_s + num.to_s).to_i 25 | end 26 | } 27 | 28 | total == target 29 | } 30 | } 31 | .map { _1.first } 32 | .sum 33 | .tap { puts _1 } 34 | -------------------------------------------------------------------------------- /2024/day-08/day-08-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'set' 4 | 5 | file_path = File.expand_path("../day-08-input.txt", __FILE__) 6 | input = File.read(file_path) 7 | 8 | grid = input.split.join.chars 9 | 10 | height = input.split.size 11 | width = input.split.first.size 12 | 13 | antennas = Hash.new { |h, k| h[k] = Set.new } 14 | 15 | grid.each.with_index 16 | .reject { _1[0] == ?. } 17 | .each { antennas[_1].add([_2 % width, _2 / width]) } 18 | 19 | antinodes = Set.new 20 | 21 | antennas.each do |_type, locations| 22 | locations.to_a.combination(2).each do |loc1, loc2| 23 | vector = loc1.zip(loc2).map { _1.inject(&:-) } 24 | 25 | loc1.zip(vector).map { _1.inject(&:+) } 26 | .tap { antinodes.add(_1) } 27 | 28 | loc2.zip(vector).map { _1.inject(&:-) } 29 | .tap { antinodes.add(_1) } 30 | end 31 | end 32 | 33 | puts antinodes 34 | .reject { |x, y| x < 0 || y < 0 || x >= width || y >= height } 35 | .count 36 | -------------------------------------------------------------------------------- /2024/day-10/day-10-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-10-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | grid = input.split.map(&:chars).map { _1.map(&:to_i) } 7 | 8 | width = grid[0].size 9 | height = grid.size 10 | 11 | start = input.split.flat_map { _1.chars }.each 12 | .map.with_index { _2 if _1 == ?0 } 13 | .compact 14 | .map { [_1 % width, _1 / width] } 15 | 16 | start.sum { |x, y| 17 | score = 0 18 | queue = [[x, y, 0]] 19 | 20 | while queue.any? 21 | x, y, lvl = queue.pop 22 | 23 | [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]] 24 | .reject { _1 < 0 || _2 < 0 || _1 >= width || _2 >= height } 25 | .select { grid[_2][_1] == lvl + 1 } 26 | .each { 27 | if lvl + 1 == 9 28 | score += 1 29 | else 30 | queue << [_1, _2, lvl + 1] 31 | end 32 | } 33 | end 34 | 35 | score 36 | }.tap { puts _1 } 37 | -------------------------------------------------------------------------------- /2024/day-11/day-11-input.txt: -------------------------------------------------------------------------------- 1 | 28591 78 0 3159881 4254 524155 598 1 2 | -------------------------------------------------------------------------------- /2024/day-11/day-11-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | stones = input.split.map(&:to_i) 7 | 8 | blinks = 25 9 | 10 | blinks.times { 11 | stones = stones.flat_map { 12 | if _1 == 0 13 | 1 14 | elsif _1.to_s.chars.count.even? 15 | digits = _1.to_s.chars 16 | length = digits.size 17 | [ 18 | digits[0..length/2 - 1].join.to_i, 19 | digits[(length/2)..-1].join.to_i 20 | ] 21 | else 22 | _1 * 2024 23 | end 24 | } 25 | } 26 | 27 | puts stones.count 28 | -------------------------------------------------------------------------------- /2024/day-11/day-11-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-11-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | blinks = 75 7 | 8 | stones = {} 9 | input.split.map(&:to_i).each { stones[_1] = 1 } 10 | 11 | blinks.times { 12 | new_stones = Hash.new { |h, k| h[k] = 0 } 13 | 14 | stones.each { |stone, count| 15 | if stone == 0 16 | new_stones[1] += count 17 | elsif stone.to_s.chars.count.even? 18 | digits = stone.to_s.chars 19 | length = digits.size 20 | 21 | left = digits[0..length/2 - 1].join.to_i 22 | right = digits[(length/2)..-1].join.to_i 23 | 24 | new_stones[left] += count 25 | new_stones[right] += count 26 | else 27 | new_stones[stone * 2024] += count 28 | end 29 | } 30 | 31 | stones = new_stones 32 | } 33 | 34 | puts stones.values.sum 35 | -------------------------------------------------------------------------------- /2024/day-13/day-13-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-13-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | machines = input.split("\n\n") 7 | 8 | machines 9 | .map { |machine| 10 | ax, ay, bx, by, px, py = machine.scan(/\d+/).map(&:to_i) 11 | 12 | sa = 0 13 | sb = 0 14 | 15 | max_b = [ 16 | px / bx, 17 | py / by, 18 | 100 19 | ].min 20 | 21 | (0..max_b).reverse_each { |b| 22 | ry = (py - b * by) 23 | next if ry % ay != 0 24 | 25 | a = ry / ay 26 | next if a > 100 27 | 28 | rx = (px - b * bx) 29 | next unless rx == 0 || (rx / a.to_f == ax) 30 | 31 | sa = a 32 | sb = b 33 | break 34 | } 35 | 36 | sa * 3 + sb 37 | } 38 | .sum 39 | .tap { puts _1 } 40 | -------------------------------------------------------------------------------- /2024/day-14/day-14-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | width = 101 7 | height = 103 8 | iter = 100 9 | 10 | robots = input.split(?\n) 11 | 12 | locations = robots.map { |robot| 13 | x, y, vx, vy = robot.scan(/-*\d+/).map(&:to_i) 14 | 15 | iter.times { 16 | x = (x + vx) % width 17 | y = (y + vy) % height 18 | } 19 | 20 | [x, y] 21 | } 22 | 23 | my = height / 2 24 | mx = width / 2 25 | 26 | x = [0...mx, (mx + 1)...width] 27 | y = [0...my, (my + 1)...height] 28 | 29 | quadrants = x.product(y) 30 | count = [0, 0, 0, 0] 31 | 32 | locations.each do |x, y| 33 | idx = quadrants.find_index { |x1, y1| 34 | x1.cover?(x) && y1.cover?(y) 35 | } 36 | 37 | count[idx] += 1 if idx 38 | end 39 | 40 | p count.inject(:*) 41 | -------------------------------------------------------------------------------- /2024/day-14/day-14-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-14-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | width = 101 7 | height = 103 8 | 9 | robots = input.split(?\n) 10 | .map { _1.scan(/-*\d+/).map(&:to_i) } 11 | 12 | seconds = 0 13 | 14 | while true 15 | seconds += 1 16 | 17 | robots.each.with_index { |(x, y, vx, vy), idx| 18 | x = (x + vx) % width 19 | y = (y + vy) % height 20 | 21 | robots[idx][0] = x 22 | robots[idx][1] = y 23 | } 24 | 25 | grid = [] 26 | 27 | height.times { 28 | grid << ?. * width 29 | } 30 | 31 | robots.each { 32 | grid[_2][_1] = ?# 33 | } 34 | 35 | grid = grid.join(?\n) 36 | 37 | if grid.include?("########") 38 | puts grid 39 | puts seconds 40 | exit 41 | end 42 | end 43 | 44 | -------------------------------------------------------------------------------- /2024/day-17/day-17-input.txt: -------------------------------------------------------------------------------- 1 | Register A: 56256477 2 | Register B: 0 3 | Register C: 0 4 | 5 | Program: 2,4,1,1,7,5,1,5,0,3,4,3,5,5,3,0 6 | -------------------------------------------------------------------------------- /2024/day-18/day-18-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-18-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | size = 71 7 | grid = ("." * size * size).chars.each_slice(size).to_a 8 | bytes = input.split.map { _1.split(?,).map(&:to_i) } 9 | 10 | bytes[0..1023].each { |x, y| 11 | grid[y][x] = ?# 12 | } 13 | 14 | start = [0, 0] 15 | 16 | queue = [] 17 | queue << [start, 0] 18 | 19 | visited = Set.new 20 | 21 | while queue.any? 22 | loc, steps = queue.pop 23 | x, y = loc 24 | 25 | candidates = [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]] 26 | 27 | candidates 28 | .reject { _1 < 0 || _2 < 0 || _1 >= size || _2 >= size } 29 | .reject { grid[_2][_1] == ?# } 30 | .reject { visited.include?([_1, _2]) } 31 | .each { 32 | if _1 == size - 1 && _2 == size - 1 33 | puts steps + 1 34 | exit 35 | end 36 | 37 | visited.add([_1, _2]) 38 | queue.unshift [[_1, _2], steps + 1] 39 | } 40 | end 41 | -------------------------------------------------------------------------------- /2024/day-19/day-19-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-19-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | towels, designs = input.split("\n\n") 7 | 8 | towels = Set.new(towels.split(?,).map(&:strip)) 9 | designs = designs.split("\n") 10 | 11 | max_length = towels.map(&:size).max 12 | 13 | designs.select { 14 | valid = false 15 | queue = [_1] 16 | 17 | while queue.any? 18 | design = queue.shift 19 | 20 | (0...[max_length, design.size].min).each do |length| 21 | target = design[0..length] 22 | 23 | if towels.include?(target) 24 | if target == design 25 | valid = true 26 | queue.clear 27 | else 28 | queue.unshift(design[length+1..]) 29 | end 30 | end 31 | end 32 | end 33 | 34 | valid 35 | }.tap { puts _1.count } 36 | -------------------------------------------------------------------------------- /2024/day-21/day-21-input.txt: -------------------------------------------------------------------------------- 1 | 340A 2 | 586A 3 | 839A 4 | 413A 5 | 968A 6 | -------------------------------------------------------------------------------- /2024/day-22/day-22-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-22-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.split.map(&:to_i) 7 | .sum { 8 | s = _1 9 | 10 | 2000.times { 11 | s = s.*(64).^(s).%(16777216) 12 | s = s./(32).^(s).%(16777216) 13 | s = s.*(2048).^(s).%(16777216) 14 | } 15 | 16 | s 17 | } 18 | .tap { p _1 } 19 | -------------------------------------------------------------------------------- /2024/day-22/day-22-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-22-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | input.split.map(&:to_i) 7 | .map { 8 | s = _1 9 | 10 | seqs = {} 11 | diffs = [] 12 | 13 | 2000.times { 14 | ns = s.*(64).^(s).%(16777216) 15 | ns = ns./(32).^(ns).%(16777216) 16 | ns = ns.*(2048).^(ns).%(16777216) 17 | 18 | diffs << (ns % 10 - s % 10) 19 | diffs = diffs[-4..] if diffs.length > 4 20 | 21 | if diffs.length == 4 22 | seqs[diffs.join(?,)] ||= ns % 10 23 | end 24 | 25 | s = ns 26 | } 27 | 28 | seqs 29 | } 30 | .inject({}) { |sums, seqs| 31 | seqs.each do |seq, sum| 32 | sums[seq] ||= 0 33 | sums[seq] += sum 34 | end 35 | 36 | sums 37 | } 38 | .tap { p _1.values.max } 39 | -------------------------------------------------------------------------------- /2024/day-23/day-23-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-23-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | connections = Hash.new { |h, k| h[k] = Set.new } 7 | 8 | input.split.each { |connection| 9 | c1, c2 = connection.split(?-) 10 | 11 | connections[c1].add(c2) 12 | connections[c2].add(c1) 13 | } 14 | 15 | triplets = Set.new 16 | 17 | connections.each { |c1, connected| 18 | connected.to_a.combination(2).each { |c2, c3| 19 | next if !connections[c2].include?(c3) 20 | triplets.add([c1, c2, c3].sort) 21 | } 22 | } 23 | 24 | triplets.to_a 25 | .map { _1.join(?,) } 26 | .count { _1.match?(/(\A|,)t/) } 27 | .tap { puts _1 } 28 | -------------------------------------------------------------------------------- /2024/day-23/day-23-part-2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-23-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | connections = Hash.new { |h, k| h[k] = Set.new } 7 | 8 | input.split.each { |connection| 9 | c1, c2 = connection.split(?-) 10 | 11 | connections[c1].add(c2) 12 | connections[c2].add(c1) 13 | } 14 | 15 | sets = Set.new 16 | 17 | input.split 18 | .map { _1.split(?-) } 19 | .each { |c1, c2| sets.add([c1, c2].sort) } 20 | 21 | while sets.count > 1 22 | p [sets.first.size, sets.count] 23 | 24 | new_sets = Set.new 25 | 26 | sets.each { |set| 27 | c1 = set.first 28 | connections[c1].each { |c2| 29 | next if set.include?(c2) 30 | next if set[1..].any? { |c3| !connections[c3].include?(c2) } 31 | 32 | new_sets.add((set.clone << c2).sort) 33 | } 34 | } 35 | 36 | sets = new_sets 37 | end 38 | 39 | puts sets.first.join(?,) 40 | -------------------------------------------------------------------------------- /2024/day-25/day-25-part-1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-25-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | 6 | schematics = input.split("\n\n") 7 | .map(&:split) 8 | 9 | locks = schematics.select { _1.first.include?(?#) } 10 | keys = schematics.select { _1.last.include?(?#) } 11 | 12 | locks = locks.map { |lock| 13 | lock.map(&:chars).transpose.map { _1.count { |col| col.include? ?# } - 1 } 14 | } 15 | 16 | keys = keys.map { |key| 17 | key.map(&:chars).transpose.map { _1.count { |col| col.include? ?# } - 1 } 18 | } 19 | 20 | keys.product(locks) 21 | .count { |key, lock| key.zip(lock).all? { _1 + _2 <= 5 } } 22 | .tap { p _1 } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advent of Code Solutions 2 | 3 | [My](https://github.com/gchan/) solutions to the programming puzzles on [Advent of Code](http://adventofcode.com/). 4 | 5 | Solutions are written in [Ruby](https://www.ruby-lang.org/en/). 6 | 7 | As of late December 2015, I decided to learn a bit about [Go](https://golang.org/) and redo the puzzles! My solutions in Go can be found [here](https://github.com/gchan/advent-of-code-go). 8 | 9 | ### What is Advent of Code? 10 | 11 | _"Advent of Code is a series of small programming puzzles for a variety of skill levels. They are self-contained and are just as appropriate for an expert who wants to stay sharp as they are for a beginner who is just learning to code. Each puzzle calls upon different skills and has two parts that build on a theme."_ 12 | 13 | ### License 14 | 15 | MIT 16 | 17 | [![Analytics](https://ga-beacon.appspot.com/UA-70790190-2/advent_of_code_ruby/README.md?flat)](https://github.com/igrigorik/ga-beacon) 18 | -------------------------------------------------------------------------------- /create_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR=$(dirname $(readlink -f $0)) 4 | 5 | for y in $(seq -w 2015 2024); do 6 | mkdir $DIR/$y 7 | 8 | for i in $(seq -w 1 25); do 9 | mkdir $DIR/$y/day-$i 10 | 11 | if [ -z "$(ls -A $DIR/$y/day-$i)" ]; then 12 | cp template.rb $DIR/$y/day-$i/day-$i-part-1.rb 13 | 14 | if [ $i -ne '25' ]; then 15 | cp template.rb $DIR/$y/day-$i/day-$i-part-2.rb 16 | fi 17 | sed -i "" "s/\\$/${i}/g" $DIR/$y/day-$i/*.rb 18 | 19 | touch $DIR/$y/day-$i/README.txt 20 | touch $DIR/$y/day-$i/day-$i-input.txt 21 | chmod +x $y/day-$i/*.rb 22 | fi 23 | done 24 | done 25 | -------------------------------------------------------------------------------- /template.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | file_path = File.expand_path("../day-$-input.txt", __FILE__) 4 | input = File.read(file_path) 5 | --------------------------------------------------------------------------------