├── .editorconfig
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── README.md
├── angular.json
├── docs
├── editor.png
├── menu.png
├── plot1.png
├── plot2.png
├── plot3.png
└── plot_animated.gif
├── karma.conf.js
├── package-lock.json
├── package.json
├── src
├── app
│ ├── app-routing.module.ts
│ ├── app.component.html
│ ├── app.component.scss
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── helper
│ │ ├── activate-route-guards
│ │ │ ├── can-activate-day.ts
│ │ │ └── can-activate-year.ts
│ │ ├── components
│ │ │ ├── animator
│ │ │ │ ├── animator.component.html
│ │ │ │ ├── animator.component.scss
│ │ │ │ └── animator.component.ts
│ │ │ ├── base-result.component.ts
│ │ │ ├── day-selection
│ │ │ │ ├── day-selection.component.html
│ │ │ │ ├── day-selection.component.scss
│ │ │ │ └── day-selection.component.ts
│ │ │ ├── plotly-graph
│ │ │ │ ├── plotly-graph.component.html
│ │ │ │ ├── plotly-graph.component.scss
│ │ │ │ └── plotly-graph.component.ts
│ │ │ ├── solution
│ │ │ │ ├── solution.component.html
│ │ │ │ ├── solution.component.scss
│ │ │ │ └── solution.component.ts
│ │ │ └── year-selection
│ │ │ │ ├── year-selection.component.html
│ │ │ │ ├── year-selection.component.scss
│ │ │ │ └── year-selection.component.ts
│ │ ├── helper.module.ts
│ │ ├── services
│ │ │ ├── base-solution.service.ts
│ │ │ ├── isolution.service.ts
│ │ │ ├── scripts-loader.service.ts
│ │ │ └── solutions-collector.service.ts
│ │ └── util-functions
│ │ │ ├── astar.ts
│ │ │ ├── big-number.ts
│ │ │ ├── chunk.ts
│ │ │ ├── color-interpolate.ts
│ │ │ ├── deque.ts
│ │ │ ├── distances.ts
│ │ │ ├── extensions.ts
│ │ │ ├── gcd.ts
│ │ │ ├── global-counter.ts
│ │ │ ├── is-number.ts
│ │ │ ├── lcm.ts
│ │ │ ├── linked-list.ts
│ │ │ ├── mod.ts
│ │ │ ├── normalize.ts
│ │ │ ├── ocr.ts
│ │ │ ├── parse-first-line-into-numbers.ts
│ │ │ ├── parse-into-2d-numbers-array.ts
│ │ │ ├── parse-into-numbers.ts
│ │ │ ├── point.ts
│ │ │ ├── product.ts
│ │ │ ├── queue.ts
│ │ │ ├── split-into-lines.ts
│ │ │ ├── stack.ts
│ │ │ ├── sum.ts
│ │ │ └── two-way-map.ts
│ ├── solutions2021
│ │ ├── components
│ │ │ ├── amphipods-room-visualizer
│ │ │ │ ├── amphipods-room-visualizer.component.html
│ │ │ │ ├── amphipods-room-visualizer.component.scss
│ │ │ │ └── amphipods-room-visualizer.component.ts
│ │ │ ├── arithmetic-logic-unit-visualizer
│ │ │ │ ├── arithmetic-logic-unit-visualizer.component.html
│ │ │ │ ├── arithmetic-logic-unit-visualizer.component.scss
│ │ │ │ └── arithmetic-logic-unit-visualizer.component.ts
│ │ │ ├── bingo-visualizer
│ │ │ │ ├── bingo-visualizer.component.html
│ │ │ │ ├── bingo-visualizer.component.scss
│ │ │ │ └── bingo-visualizer.component.ts
│ │ │ ├── bits-visualizer
│ │ │ │ ├── bits-visualizer.component.html
│ │ │ │ ├── bits-visualizer.component.scss
│ │ │ │ └── bits-visualizer.component.ts
│ │ │ ├── caves-visualizer
│ │ │ │ ├── caves-visualizer.component.html
│ │ │ │ ├── caves-visualizer.component.scss
│ │ │ │ └── caves-visualizer.component.ts
│ │ │ ├── ocean-trench-visualizer
│ │ │ │ ├── ocean-trench-visualizer.component.html
│ │ │ │ ├── ocean-trench-visualizer.component.scss
│ │ │ │ └── ocean-trench-visualizer.component.ts
│ │ │ ├── octopus-flashes-visualizer
│ │ │ │ ├── octopus-flashes-visualizer.component.html
│ │ │ │ ├── octopus-flashes-visualizer.component.scss
│ │ │ │ └── octopus-flashes-visualizer.component.ts
│ │ │ ├── sea-cucumbers-visualizer
│ │ │ │ ├── sea-cucumbers-visualizer.component.html
│ │ │ │ ├── sea-cucumbers-visualizer.component.scss
│ │ │ │ └── sea-cucumbers-visualizer.component.ts
│ │ │ ├── seven-segments-display-visualizer
│ │ │ │ ├── seven-segments-display-visualizer.component.html
│ │ │ │ ├── seven-segments-display-visualizer.component.scss
│ │ │ │ └── seven-segments-display-visualizer.component.ts
│ │ │ ├── snailfish-number-visualizer
│ │ │ │ ├── snailfish-number-visualizer.component.html
│ │ │ │ ├── snailfish-number-visualizer.component.scss
│ │ │ │ └── snailfish-number-visualizer.component.ts
│ │ │ └── syntax-error-lines-visualizer
│ │ │ │ ├── syntax-error-lines-visualizer.component.html
│ │ │ │ ├── syntax-error-lines-visualizer.component.scss
│ │ │ │ └── syntax-error-lines-visualizer.component.ts
│ │ ├── day1.service.ts
│ │ ├── day10.service.ts
│ │ ├── day11.service.ts
│ │ ├── day12.service.ts
│ │ ├── day13.service.ts
│ │ ├── day14.service.ts
│ │ ├── day15.service.ts
│ │ ├── day16.service.ts
│ │ ├── day17.service.ts
│ │ ├── day18.service.ts
│ │ ├── day19.service.ts
│ │ ├── day2.service.ts
│ │ ├── day20.service.ts
│ │ ├── day21.service.ts
│ │ ├── day22.service.ts
│ │ ├── day23.service.ts
│ │ ├── day24.service.ts
│ │ ├── day25.service.ts
│ │ ├── day3.service.ts
│ │ ├── day4.service.ts
│ │ ├── day5.service.ts
│ │ ├── day6.service.ts
│ │ ├── day7.service.ts
│ │ ├── day8.service.ts
│ │ ├── day9.service.ts
│ │ └── solutions2021.module.ts
│ ├── solutions2022
│ │ ├── components
│ │ │ ├── blizzard-visualizer
│ │ │ │ ├── blizzard-visualizer.component.html
│ │ │ │ ├── blizzard-visualizer.component.scss
│ │ │ │ └── blizzard-visualizer.component.ts
│ │ │ ├── camp-sections-visualizer
│ │ │ │ ├── camp-sections-visualizer.component.html
│ │ │ │ ├── camp-sections-visualizer.component.scss
│ │ │ │ └── camp-sections-visualizer.component.ts
│ │ │ ├── cargo-visualizer
│ │ │ │ ├── cargo-step-visualizer
│ │ │ │ │ ├── cargo-step-visualizer.component.html
│ │ │ │ │ ├── cargo-step-visualizer.component.scss
│ │ │ │ │ └── cargo-step-visualizer.component.ts
│ │ │ │ ├── cargo-visualizer.component.html
│ │ │ │ ├── cargo-visualizer.component.scss
│ │ │ │ └── cargo-visualizer.component.ts
│ │ │ ├── datastream-buffer-visualizer
│ │ │ │ ├── datastream-buffer-visualizer.component.html
│ │ │ │ ├── datastream-buffer-visualizer.component.scss
│ │ │ │ └── datastream-buffer-visualizer.component.ts
│ │ │ ├── device-file-visualizer
│ │ │ │ ├── device-file-visualizer.component.html
│ │ │ │ ├── device-file-visualizer.component.scss
│ │ │ │ └── device-file-visualizer.component.ts
│ │ │ ├── elves-moves-visualizer
│ │ │ │ ├── elves-moves-visualizer.component.html
│ │ │ │ ├── elves-moves-visualizer.component.scss
│ │ │ │ └── elves-moves-visualizer.component.ts
│ │ │ ├── falling-rocks-visualizer
│ │ │ │ ├── falling-rocks-visualizer.component.html
│ │ │ │ ├── falling-rocks-visualizer.component.scss
│ │ │ │ └── falling-rocks-visualizer.component.ts
│ │ │ ├── falling-sand-visualizer
│ │ │ │ ├── falling-sand-visualizer.component.html
│ │ │ │ ├── falling-sand-visualizer.component.scss
│ │ │ │ └── falling-sand-visualizer.component.ts
│ │ │ ├── monkey-map-cube-visualizer
│ │ │ │ ├── monkey-map-cube-visualizer.component.html
│ │ │ │ ├── monkey-map-cube-visualizer.component.scss
│ │ │ │ ├── monkey-map-cube-visualizer.component.ts
│ │ │ │ └── orbit-controls.ts
│ │ │ ├── monkey-math-equations-visualizer
│ │ │ │ ├── monkey-math-equations-visualizer.component.html
│ │ │ │ ├── monkey-math-equations-visualizer.component.scss
│ │ │ │ └── monkey-math-equations-visualizer.component.ts
│ │ │ ├── monkeys-inspections-visualizer
│ │ │ │ ├── monkey-inspection-visualizer
│ │ │ │ │ ├── monkey-inspection-visualizer.component.html
│ │ │ │ │ ├── monkey-inspection-visualizer.component.scss
│ │ │ │ │ └── monkey-inspection-visualizer.component.ts
│ │ │ │ ├── monkeys-inspections-visualizer.component.html
│ │ │ │ ├── monkeys-inspections-visualizer.component.scss
│ │ │ │ └── monkeys-inspections-visualizer.component.ts
│ │ │ ├── packet-numbers-visualizer
│ │ │ │ ├── packet-numbers-visualizer.component.html
│ │ │ │ ├── packet-numbers-visualizer.component.scss
│ │ │ │ └── packet-numbers-visualizer.component.ts
│ │ │ ├── pressure-valves-visualizer
│ │ │ │ ├── pressure-valves-visualizer.component.html
│ │ │ │ ├── pressure-valves-visualizer.component.scss
│ │ │ │ └── pressure-valves-visualizer.component.ts
│ │ │ ├── rope-bridge-visualizer
│ │ │ │ ├── rope-bridge-visualizer.component.html
│ │ │ │ ├── rope-bridge-visualizer.component.scss
│ │ │ │ └── rope-bridge-visualizer.component.ts
│ │ │ └── snafu-numbers-visualizer
│ │ │ │ ├── snafu-numbers-visualizer.component.html
│ │ │ │ ├── snafu-numbers-visualizer.component.scss
│ │ │ │ └── snafu-numbers-visualizer.component.ts
│ │ ├── day1.service.ts
│ │ ├── day10.service.ts
│ │ ├── day11.service.ts
│ │ ├── day12.service.ts
│ │ ├── day13.service.ts
│ │ ├── day14.service.ts
│ │ ├── day15.service.ts
│ │ ├── day16.service.ts
│ │ ├── day17.service.ts
│ │ ├── day18.service.ts
│ │ ├── day19.service.ts
│ │ ├── day2.service.ts
│ │ ├── day20.service.ts
│ │ ├── day21.service.ts
│ │ ├── day22.service.ts
│ │ ├── day23.service.ts
│ │ ├── day24.service.ts
│ │ ├── day25.service.ts
│ │ ├── day3.service.ts
│ │ ├── day4.service.ts
│ │ ├── day5.service.ts
│ │ ├── day6.service.ts
│ │ ├── day7.service.ts
│ │ ├── day8.service.ts
│ │ ├── day9.service.ts
│ │ ├── helper
│ │ │ ├── day16.ts
│ │ │ └── day19.ts
│ │ ├── solutions2022.module.ts
│ │ └── web-workers
│ │ │ ├── day16.worker.ts
│ │ │ └── day19.worker.ts
│ └── template
│ │ └── solution-template.service.ts
├── assets
│ ├── .gitkeep
│ └── inputs
│ │ ├── 2021
│ │ ├── 1.txt
│ │ ├── 10.txt
│ │ ├── 11.txt
│ │ ├── 12.txt
│ │ ├── 13.txt
│ │ ├── 14.txt
│ │ ├── 15.txt
│ │ ├── 16.txt
│ │ ├── 17.txt
│ │ ├── 18.txt
│ │ ├── 19.txt
│ │ ├── 2.txt
│ │ ├── 20.txt
│ │ ├── 21.txt
│ │ ├── 22.txt
│ │ ├── 23.txt
│ │ ├── 24.txt
│ │ ├── 25.txt
│ │ ├── 3.txt
│ │ ├── 4.txt
│ │ ├── 5.txt
│ │ ├── 6.txt
│ │ ├── 7.txt
│ │ ├── 8.txt
│ │ └── 9.txt
│ │ └── 2022
│ │ ├── 1.txt
│ │ ├── 10.txt
│ │ ├── 11.txt
│ │ ├── 12.txt
│ │ ├── 13.txt
│ │ ├── 14.txt
│ │ ├── 15.txt
│ │ ├── 16.txt
│ │ ├── 17.txt
│ │ ├── 18.txt
│ │ ├── 19.txt
│ │ ├── 2.txt
│ │ ├── 20.txt
│ │ ├── 21.txt
│ │ ├── 22.txt
│ │ ├── 23.txt
│ │ ├── 24.txt
│ │ ├── 25.txt
│ │ ├── 3.txt
│ │ ├── 4.txt
│ │ ├── 5.txt
│ │ ├── 6.txt
│ │ ├── 7.txt
│ │ ├── 8.txt
│ │ └── 9.txt
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.scss
└── test.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
└── tsconfig.worker.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.ts]
12 | quote_type = single
13 |
14 | [*.md]
15 | max_line_length = off
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build and Deploy
2 | on:
3 | push:
4 | branches:
5 | - main
6 | pull_request:
7 | branches:
8 | - main
9 | jobs:
10 | build-and-deploy:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout 🛎️
14 | uses: actions/checkout@v2.3.1
15 |
16 | - name: Download required Node version ⬇️
17 | uses: actions/setup-node@v3
18 | with:
19 | node-version: '16'
20 | cache: 'npm'
21 |
22 | - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
23 | run: |
24 | npm ci
25 | npm run build-gh
26 |
27 | - name: Deploy 🚀
28 | uses: JamesIves/github-pages-deploy-action@4.1.7
29 | with:
30 | branch: page # The branch the action should deploy to.
31 | folder: dist/AdventOfCode # The folder the action should deploy.
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | # Only exists if Bazel was run
8 | /bazel-out
9 |
10 | # dependencies
11 | /node_modules
12 |
13 | # profiling files
14 | chrome-profiler-events*.json
15 |
16 | # IDEs and editors
17 | /.idea
18 | .project
19 | .classpath
20 | .c9/
21 | *.launch
22 | .settings/
23 | *.sublime-workspace
24 |
25 | # IDE - VSCode
26 | .vscode/*
27 | !.vscode/settings.json
28 | !.vscode/tasks.json
29 | !.vscode/launch.json
30 | !.vscode/extensions.json
31 | .history/*
32 |
33 | # misc
34 | /.angular/cache
35 | /.sass-cache
36 | /connect.lock
37 | /coverage
38 | /libpeerconnection.log
39 | npm-debug.log
40 | yarn-error.log
41 | testem.log
42 | /typings
43 |
44 | # System Files
45 | .DS_Store
46 | Thumbs.db
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [AdventOfCode Angular](https://raczeq.github.io/AdventOfCodeAngular/)
2 |
3 | An interactive page with solutions written in the TypeScript language with Angular framework.
4 |
5 | https://raczeq.github.io/AdventOfCodeAngular/
6 |
7 | 
8 |
9 | Page loads base input automatically, but allows you to paste your own into a provided form. Input link opens up your input page from Advent Of Code website.
10 |
11 | 
12 |
13 | After clicking run, solution and visualizations are generated on your browser. Clicking on results will automatically copy it to your clipboard.
14 |
15 | 
16 |
17 | 
18 |
19 | 
20 |
21 | 
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "AdventOfCode": {
7 | "projectType": "application",
8 | "schematics": {
9 | "@schematics/angular:component": {
10 | "style": "scss",
11 | "skipTests": true
12 | },
13 | "@schematics/angular:class": {
14 | "skipTests": true
15 | },
16 | "@schematics/angular:directive": {
17 | "skipTests": true
18 | },
19 | "@schematics/angular:guard": {
20 | "skipTests": true
21 | },
22 | "@schematics/angular:interceptor": {
23 | "skipTests": true
24 | },
25 | "@schematics/angular:pipe": {
26 | "skipTests": true
27 | },
28 | "@schematics/angular:service": {
29 | "skipTests": true
30 | },
31 | "@schematics/angular:application": {
32 | "strict": true
33 | }
34 | },
35 | "root": "",
36 | "sourceRoot": "src",
37 | "prefix": "aoc",
38 | "architect": {
39 | "build": {
40 | "builder": "@angular-devkit/build-angular:browser",
41 | "options": {
42 | "outputPath": "dist/AdventOfCode",
43 | "index": "src/index.html",
44 | "main": "src/main.ts",
45 | "polyfills": "src/polyfills.ts",
46 | "tsConfig": "tsconfig.app.json",
47 | "inlineStyleLanguage": "scss",
48 | "assets": ["src/favicon.ico", "src/assets"],
49 | "styles": ["src/styles.scss"],
50 | "scripts": [],
51 | "webWorkerTsConfig": "tsconfig.worker.json"
52 | },
53 | "configurations": {
54 | "production": {
55 | "budgets": [],
56 | "fileReplacements": [
57 | {
58 | "replace": "src/environments/environment.ts",
59 | "with": "src/environments/environment.prod.ts"
60 | }
61 | ],
62 | "outputHashing": "all"
63 | },
64 | "development": {
65 | "buildOptimizer": false,
66 | "optimization": false,
67 | "vendorChunk": true,
68 | "extractLicenses": false,
69 | "sourceMap": true,
70 | "namedChunks": true
71 | }
72 | },
73 | "defaultConfiguration": "production"
74 | },
75 | "serve": {
76 | "builder": "@angular-devkit/build-angular:dev-server",
77 | "configurations": {
78 | "production": {
79 | "browserTarget": "AdventOfCode:build:production"
80 | },
81 | "development": {
82 | "browserTarget": "AdventOfCode:build:development"
83 | }
84 | },
85 | "defaultConfiguration": "development"
86 | },
87 | "extract-i18n": {
88 | "builder": "@angular-devkit/build-angular:extract-i18n",
89 | "options": {
90 | "browserTarget": "AdventOfCode:build"
91 | }
92 | },
93 | "test": {
94 | "builder": "@angular-devkit/build-angular:karma",
95 | "options": {
96 | "main": "src/test.ts",
97 | "polyfills": "src/polyfills.ts",
98 | "tsConfig": "tsconfig.spec.json",
99 | "karmaConfig": "karma.conf.js",
100 | "inlineStyleLanguage": "scss",
101 | "assets": ["src/favicon.ico", "src/assets"],
102 | "styles": ["src/styles.scss"],
103 | "scripts": [],
104 | "webWorkerTsConfig": "tsconfig.worker.json"
105 | }
106 | }
107 | }
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/docs/editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/docs/editor.png
--------------------------------------------------------------------------------
/docs/menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/docs/menu.png
--------------------------------------------------------------------------------
/docs/plot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/docs/plot1.png
--------------------------------------------------------------------------------
/docs/plot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/docs/plot2.png
--------------------------------------------------------------------------------
/docs/plot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/docs/plot3.png
--------------------------------------------------------------------------------
/docs/plot_animated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/docs/plot_animated.gif
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | jasmine: {
17 | // you can add configuration options for Jasmine here
18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19 | // for example, you can disable the random execution with `random: false`
20 | // or set a specific seed with `seed: 4321`
21 | },
22 | clearContext: false // leave Jasmine Spec Runner output visible in browser
23 | },
24 | jasmineHtmlReporter: {
25 | suppressAll: true // removes the duplicated traces
26 | },
27 | coverageReporter: {
28 | dir: require('path').join(__dirname, './coverage/AdventOfCode'),
29 | subdir: '.',
30 | reporters: [
31 | { type: 'html' },
32 | { type: 'text-summary' }
33 | ]
34 | },
35 | reporters: ['progress', 'kjhtml'],
36 | port: 9876,
37 | colors: true,
38 | logLevel: config.LOG_INFO,
39 | autoWatch: true,
40 | browsers: ['Chrome'],
41 | singleRun: false,
42 | restartOnFileChange: true
43 | });
44 | };
45 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "advent-of-code",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "build-gh": "ng build --base-href https://raczeq.github.io/AdventOfCodeAngular/",
9 | "watch": "ng build --watch --configuration development",
10 | "test": "ng test"
11 | },
12 | "private": true,
13 | "dependencies": {
14 | "@angular/animations": "^15.0.1",
15 | "@angular/cdk": "^15.0.0",
16 | "@angular/common": "^15.0.1",
17 | "@angular/compiler": "^15.0.1",
18 | "@angular/core": "^15.0.1",
19 | "@angular/forms": "^15.0.1",
20 | "@angular/material": "^15.0.0",
21 | "@angular/platform-browser": "^15.0.1",
22 | "@angular/platform-browser-dynamic": "^15.0.1",
23 | "@angular/router": "^15.0.1",
24 | "angular-plotly.js": "^4.0.4",
25 | "plotly.js-dist-min": "^2.7.0",
26 | "rxjs": "~7.4.0",
27 | "tslib": "^2.3.0",
28 | "zone.js": "~0.11.4"
29 | },
30 | "devDependencies": {
31 | "@angular-devkit/build-angular": "^15.0.1",
32 | "@angular/cli": "^15.0.1",
33 | "@angular/compiler-cli": "^15.0.1",
34 | "@types/jasmine": "~3.10.0",
35 | "@types/node": "^12.11.1",
36 | "@types/plotly.js-dist-min": "^2.3.0",
37 | "jasmine-core": "~3.10.0",
38 | "karma": "~6.3.0",
39 | "karma-chrome-launcher": "~3.1.0",
40 | "karma-coverage": "~2.0.3",
41 | "karma-jasmine": "~4.0.0",
42 | "karma-jasmine-html-reporter": "~1.7.0",
43 | "typescript": "~4.8.4"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { CanActivateDay } from './helper/activate-route-guards/can-activate-day';
4 | import { CanActivateYear } from './helper/activate-route-guards/can-activate-year';
5 | import { DaySelectionComponent } from './helper/components/day-selection/day-selection.component';
6 | import { SolutionComponent } from './helper/components/solution/solution.component';
7 | import { YearSelectionComponent } from './helper/components/year-selection/year-selection.component';
8 |
9 | const routes: Routes = [
10 | {
11 | path: ':year/:day',
12 | canActivate: [CanActivateDay],
13 | component: SolutionComponent,
14 | },
15 | {
16 | path: ':year',
17 | canActivate: [CanActivateYear],
18 | component: DaySelectionComponent,
19 | },
20 | {
21 | path: '',
22 | component: YearSelectionComponent,
23 | pathMatch: 'full',
24 | },
25 | { path: '**', redirectTo: '/' },
26 | ];
27 |
28 | @NgModule({
29 | imports: [
30 | RouterModule.forRoot(routes, {
31 | useHash: true,
32 | }),
33 | ],
34 | exports: [RouterModule],
35 | })
36 | export class AppRoutingModule {}
37 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
4 |
10 | Advent Of Code
11 | 0"
13 | class="accent-color"
14 | [style.margin-left.em]="1"
15 | routerLink="/{{ selectedYear }}"
16 | >{{ selectedYear }}
18 | {{ actionName }}
24 | 0 && selectedDay > 0 && canGoToPreviousDay"
26 | class="navigator accent-color"
27 | [style.margin-left.em]="1"
28 | routerLink="/{{ selectedYear }}/{{ selectedDay - 1 }}"
29 | >
30 | Previous day
31 |
32 | 0 && selectedDay > 0 && !canGoToPreviousDay"
34 | class="navigator disabled-navigator"
35 | [style.margin-left.em]="1"
36 | >
37 | Previous day
38 |
39 | 0 && selectedDay > 0 && canGoToNextDay"
41 | class="navigator accent-color"
42 | [style.margin-left.em]="1"
43 | routerLink="/{{ selectedYear }}/{{ selectedDay + 1 }}"
44 | >
45 | Next day
46 |
47 | 0 && selectedDay > 0 && !canGoToNextDay"
49 | class="navigator disabled-navigator"
50 | [style.margin-left.em]="1"
51 | >
52 | Next day
53 |
54 |
55 |
56 | code
57 | Github repository
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 | @use "@angular/material" as mat;
2 | @use "sass:math";
3 |
4 | @function random_range($min, $max) {
5 | $rand: random();
6 | $random_range: $min + floor($rand * (($max - $min) + 1));
7 | @return $random_range;
8 | }
9 |
10 | :host {
11 | z-index: 1;
12 | height: 100vh;
13 | width: 100vw;
14 | display: flex;
15 | flex-direction: column;
16 | background: linear-gradient(#000428, #0f0f23);
17 |
18 | .router-container {
19 | padding-top: 64px;
20 | flex: 1;
21 | overflow: auto;
22 | z-index: 1;
23 | }
24 |
25 | .navigator {
26 | cursor: pointer;
27 | @media screen and (max-width: 600px) {
28 | display: none;
29 | }
30 | }
31 |
32 | .disabled-navigator {
33 | color: rgba(255, 255, 255, 0.2);
34 | }
35 |
36 | .code-icon {
37 | vertical-align: middle;
38 | padding-bottom: 2px;
39 | }
40 |
41 | .snow-background {
42 | z-index: 0;
43 | position: absolute;
44 | height: 100vh;
45 | width: 100vw;
46 | top: 0;
47 | left: 0;
48 | overflow: hidden;
49 | filter: drop-shadow(0 0 5px white);
50 |
51 | .snow {
52 | $total: 200;
53 | position: absolute;
54 | width: 10px;
55 | height: 10px;
56 | background: white;
57 | border-radius: 50%;
58 |
59 | @for $i from 1 through $total {
60 | $random-x: random(1000000) * 0.0001vw;
61 | $random-offset: random_range(-100000, 100000) * 0.0001vw;
62 | $random-x-end: $random-x + $random-offset;
63 | $random-x-end-yoyo: $random-x + math.div($random-offset, 2);
64 | $random-yoyo-time: math.div(random_range(30000, 80000), 100000);
65 | $random-yoyo-y: $random-yoyo-time * 100vh;
66 | $random-scale: random(10000) * 0.0001;
67 | $fall-duration: random_range(10, 30) * 1s;
68 | $fall-delay: random(30) * -1s;
69 |
70 | &:nth-child(#{$i}) {
71 | opacity: random(10000) * 0.0001;
72 | transform: translate($random-x, -10px) scale($random-scale);
73 | animation: fall-#{$i} $fall-duration $fall-delay linear infinite;
74 | }
75 |
76 | @keyframes fall-#{$i} {
77 | #{percentage($random-yoyo-time)} {
78 | transform: translate($random-x-end, $random-yoyo-y)
79 | scale($random-scale);
80 | }
81 |
82 | to {
83 | transform: translate($random-x-end-yoyo, 100vh) scale($random-scale);
84 | }
85 | }
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { ActivationEnd, Router } from '@angular/router';
3 | import {
4 | AvailableSolutions,
5 | SolutionsCollectorService,
6 | } from './helper/services/solutions-collector.service';
7 |
8 | @Component({
9 | selector: 'aoc-root',
10 | templateUrl: './app.component.html',
11 | styleUrls: ['./app.component.scss'],
12 | })
13 | export class AppComponent {
14 | title = 'AdventOfCode';
15 | selectedYear: number = 0;
16 | selectedDay: number = 0;
17 | actionName: string = '';
18 | availableSolutions: AvailableSolutions = {};
19 | constructor(
20 | private router: Router,
21 | private solutionsCollectorService: SolutionsCollectorService
22 | ) {
23 | router.events.subscribe((event) => {
24 | if (event instanceof ActivationEnd) {
25 | this.selectedYear = Number(event.snapshot.params['year']);
26 | this.selectedDay = Number(event.snapshot.params['day']);
27 | if (this.selectedDay) {
28 | this.actionName = 'Go back';
29 | } else if (this.selectedYear) {
30 | this.actionName = 'Select day';
31 | } else {
32 | this.actionName = 'Select year';
33 | }
34 | }
35 | });
36 |
37 | solutionsCollectorService
38 | .getAvailableSolutionsObservable()
39 | .subscribe((solutions) => (this.availableSolutions = solutions));
40 | }
41 |
42 | get canGoToPreviousDay(): boolean {
43 | return this.selectedDay - 1 in this.availableSolutions[this.selectedYear];
44 | }
45 |
46 | get canGoToNextDay(): boolean {
47 | return this.selectedDay + 1 in this.availableSolutions[this.selectedYear];
48 | }
49 |
50 | goToRepo(): void {
51 | window.open('https://github.com/RaczeQ/AdventOfCodeAngular', '_blank');
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 |
4 | import { AppRoutingModule } from './app-routing.module';
5 | import { AppComponent } from './app.component';
6 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
7 | import { RouterModule } from '@angular/router';
8 |
9 | import { MatToolbarModule } from '@angular/material/toolbar';
10 | import { MatIconModule } from '@angular/material/icon';
11 |
12 | import { Solutions2021Module } from './solutions2021/solutions2021.module';
13 | import { Solutions2022Module } from './solutions2022/solutions2022.module';
14 |
15 | @NgModule({
16 | declarations: [AppComponent],
17 | imports: [
18 | BrowserModule,
19 | AppRoutingModule,
20 | BrowserAnimationsModule,
21 | RouterModule,
22 | MatToolbarModule,
23 | MatIconModule,
24 | Solutions2021Module,
25 | Solutions2022Module,
26 | ],
27 | providers: [],
28 | bootstrap: [AppComponent],
29 | })
30 | export class AppModule {}
31 |
--------------------------------------------------------------------------------
/src/app/helper/activate-route-guards/can-activate-day.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import {
3 | ActivatedRouteSnapshot,
4 | CanActivate,
5 | Router,
6 | RouterStateSnapshot,
7 | UrlTree,
8 | } from '@angular/router';
9 | import { Observable } from 'rxjs';
10 | import {
11 | AvailableSolutions,
12 | SolutionsCollectorService,
13 | } from '../services/solutions-collector.service';
14 |
15 | @Injectable()
16 | export class CanActivateDay implements CanActivate {
17 | availableSolutions: AvailableSolutions = {};
18 | constructor(
19 | private solutionsCollectorService: SolutionsCollectorService,
20 | private router: Router
21 | ) {
22 | solutionsCollectorService
23 | .getAvailableSolutionsObservable()
24 | .subscribe((solutions) => (this.availableSolutions = solutions));
25 | }
26 |
27 | canActivate(
28 | route: ActivatedRouteSnapshot,
29 | state: RouterStateSnapshot
30 | ):
31 | | Observable
32 | | Promise
33 | | boolean
34 | | UrlTree {
35 | var year = route.params['year'];
36 | var yearNumber = Number(year);
37 | var day = route.params['day'];
38 | var dayNumber = Number(day);
39 | var result =
40 | day &&
41 | this.isInt(day) &&
42 | yearNumber in this.availableSolutions &&
43 | dayNumber in this.availableSolutions[yearNumber];
44 | if (!result) {
45 | this.router.navigate(['/', yearNumber]);
46 | }
47 | return result;
48 | }
49 |
50 | isInt(value: any) {
51 | return (
52 | !isNaN(value) &&
53 | parseInt(Number(value).toString()) == value &&
54 | !isNaN(parseInt(value, 10))
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/app/helper/activate-route-guards/can-activate-year.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import {
3 | ActivatedRouteSnapshot,
4 | CanActivate,
5 | Router,
6 | RouterStateSnapshot,
7 | UrlTree,
8 | } from '@angular/router';
9 | import { Observable } from 'rxjs';
10 | import { SolutionsCollectorService } from '../services/solutions-collector.service';
11 |
12 | @Injectable()
13 | export class CanActivateYear implements CanActivate {
14 | availableYears: number[] = [];
15 | constructor(
16 | private solutionsCollectorService: SolutionsCollectorService,
17 | private router: Router
18 | ) {
19 | solutionsCollectorService
20 | .getAvailableYearsObservable()
21 | .subscribe((years) => (this.availableYears = years));
22 | }
23 |
24 | canActivate(
25 | route: ActivatedRouteSnapshot,
26 | state: RouterStateSnapshot
27 | ):
28 | | Observable
29 | | Promise
30 | | boolean
31 | | UrlTree {
32 | var year = route.params['year'];
33 | var yearNumber = Number(year);
34 | var result =
35 | year && this.isInt(year) && this.availableYears.includes(yearNumber);
36 | if (!result) {
37 | this.router.navigate(['/']);
38 | }
39 | return result;
40 | }
41 |
42 | isInt(value: any) {
43 | return (
44 | !isNaN(value) &&
45 | parseInt(Number(value).toString()) == value &&
46 | !isNaN(parseInt(value, 10))
47 | );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/app/helper/components/animator/animator.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
21 |
30 |
39 |
48 |
57 |
58 |
59 | Animation speed: {{ interval }}ms
60 |
61 |
68 |
69 |
70 |
71 | Iterations: {{ currentIdx + 1 }} / {{ iterations }} ({{
72 | (100 * currentIdx) / (iterations - 1) | number : "1.0-2"
73 | }}%)
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/app/helper/components/animator/animator.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/helper/components/animator/animator.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, EventEmitter, Input, Output } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'aoc-animator',
5 | templateUrl: './animator.component.html',
6 | styleUrls: ['./animator.component.scss'],
7 | })
8 | export class AnimatorComponent {
9 | currentIdx: number = 0;
10 | visualizing: boolean = false;
11 | interval = 100;
12 | @Input() iterations: number = 0;
13 | @Output() currentIdxEvent = new EventEmitter();
14 |
15 | resetVisualization() {
16 | this.currentIdx = 0;
17 | this.currentIdxEvent.emit(this.currentIdx);
18 | }
19 |
20 | goToEnd() {
21 | this.currentIdx = this.iterations - 1;
22 | this.currentIdxEvent.emit(this.currentIdx);
23 | }
24 |
25 | pauseVisualization() {
26 | this.visualizing = false;
27 | }
28 |
29 | startVisualization() {
30 | this.visualizing = true;
31 | if (this.currentIdx == this.iterations - 1) {
32 | this.resetVisualization();
33 | }
34 | this.loop();
35 | }
36 |
37 | nextStep() {
38 | this.currentIdx++;
39 | this.currentIdxEvent.emit(this.currentIdx);
40 | }
41 |
42 | prevStep() {
43 | this.currentIdx--;
44 | this.currentIdxEvent.emit(this.currentIdx);
45 | }
46 |
47 | private loop() {
48 | if (this.visualizing) {
49 | setTimeout(() => {
50 | this.nextStep();
51 | if (this.currentIdx < this.iterations - 1) {
52 | this.loop();
53 | } else {
54 | this.visualizing = false;
55 | }
56 | }, this.interval);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/app/helper/components/base-result.component.ts:
--------------------------------------------------------------------------------
1 | import { Directive, Input } from "@angular/core";
2 |
3 | @Directive()
4 | export abstract class BaseResultComponent {
5 | @Input() data: any;
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/helper/components/day-selection/day-selection.component.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | Day
9 | {{
10 | day[0]
11 | }}
12 |
13 | {{ day[1] }}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/app/helper/components/day-selection/day-selection.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex-flow: row wrap;
4 | mat-card {
5 | margin: 2em;
6 | cursor: pointer;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/helper/components/day-selection/day-selection.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { ActivatedRoute } from '@angular/router';
3 | import { SolutionsCollectorService } from '../../services/solutions-collector.service';
4 |
5 | @Component({
6 | selector: 'aoc-day-selection',
7 | templateUrl: './day-selection.component.html',
8 | styleUrls: ['./day-selection.component.scss'],
9 | })
10 | export class DaySelectionComponent {
11 | availableDays: [number, string][] = [];
12 | constructor(
13 | private solutionsCollectorService: SolutionsCollectorService,
14 | private route: ActivatedRoute
15 | ) {
16 | var year = route.snapshot.params["year"];
17 | this.solutionsCollectorService
18 | .getAvailableDaysObservable(year)
19 | .subscribe((days) => (this.availableDays = days));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/helper/components/plotly-graph/plotly-graph.component.html:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/app/helper/components/plotly-graph/plotly-graph.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/src/app/helper/components/plotly-graph/plotly-graph.component.scss
--------------------------------------------------------------------------------
/src/app/helper/components/plotly-graph/plotly-graph.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from '../base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-plotly-graph',
6 | templateUrl: './plotly-graph.component.html',
7 | styleUrls: ['./plotly-graph.component.scss'],
8 | })
9 | export class PlotlyGraphComponent
10 | extends BaseResultComponent
11 | implements OnInit
12 | {
13 | // graphData: Plotly.Data[] = [];
14 | // graphLayout: Partial = {};
15 | // graphConfig: Partial = {};
16 |
17 | graphData: any[] = [];
18 | graphLayout: any = {};
19 | graphConfig: any = {};
20 |
21 | ngOnInit(): void {
22 | this.graphData = this.data.graphData ?? [];
23 | this.graphLayout = this.data.graphLayout ?? {};
24 | this.graphLayout.margin = {
25 | l: 64,
26 | r: 64,
27 | b: 32,
28 | t: 32,
29 | // pad: 0
30 | };
31 | this.graphLayout.paper_bgcolor = 'rgba(0,0,0,0)';
32 | this.graphLayout.plot_bgcolor = 'rgba(0,0,0,0)';
33 | this.graphLayout.legend = {
34 | font: {
35 | color: '#ffffff',
36 | },
37 | };
38 | if (!this.graphLayout.xaxis) {
39 | this.graphLayout.xaxis = {};
40 | }
41 | this.graphLayout.xaxis.showgrid = false;
42 | this.graphLayout.xaxis.zeroline = false;
43 | this.graphLayout.xaxis.showline = true;
44 | this.graphLayout.xaxis.color = '#ffffff';
45 | this.graphLayout.xaxis.tickfont = {
46 | color: '#ffffff',
47 | };
48 | if (!this.graphLayout.yaxis) {
49 | this.graphLayout.yaxis = {};
50 | }
51 | this.graphLayout.yaxis.showgrid = false;
52 | this.graphLayout.yaxis.showline = true;
53 | this.graphLayout.yaxis.zeroline = false;
54 | this.graphLayout.yaxis.color = '#ffffff';
55 | this.graphLayout.yaxis.tickfont = {
56 | color: '#ffffff',
57 | };
58 | if (!this.graphLayout.yaxis2) {
59 | this.graphLayout.yaxis2 = {};
60 | }
61 | this.graphLayout.yaxis2.showgrid = false;
62 | this.graphLayout.yaxis2.showline = true;
63 | this.graphLayout.yaxis2.zeroline = false;
64 | this.graphLayout.yaxis2.color = '#ffffff';
65 | this.graphLayout.yaxis2.tickfont = {
66 | color: '#ffffff',
67 | };
68 | if (!this.graphLayout.scene) {
69 | this.graphLayout.scene = {};
70 | (['xaxis', 'yaxis', 'zaxis'] as ('xaxis' | 'yaxis' | 'zaxis')[]).forEach(
71 | (ax) => {
72 | this.graphLayout.scene![ax] = {
73 | showgrid: true,
74 | zeroline: true,
75 | showline: true,
76 | color: '#ffffff',
77 | tickfont: {
78 | color: '#ffffff',
79 | },
80 | };
81 | }
82 | );
83 | }
84 |
85 | this.graphConfig = this.data.graphConfig ?? {
86 | displayModeBar: false,
87 | staticPlot: true,
88 | };
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/app/helper/components/solution/solution.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | margin: 2rem;
3 | display: block;
4 | }
5 |
6 | .flex-row {
7 | display: flex;
8 | margin-bottom: 2em;
9 | }
10 |
11 | .input-link {
12 | margin-right: 2em;
13 | display: flex;
14 | justify-content: center;
15 |
16 | mat-card-title {
17 | margin: auto;
18 | }
19 |
20 | .link {
21 | text-decoration: none;
22 | background-color: none;
23 | &:hover {
24 | text-decoration: none;
25 | }
26 | }
27 |
28 | @media screen and (max-width: 600px) {
29 | display: none;
30 | }
31 | }
32 |
33 | .day-name {
34 | cursor: pointer;
35 | }
36 |
37 | .run-button {
38 | display: flex;
39 | justify-content: center;
40 | button {
41 | margin: auto;
42 | }
43 | }
44 |
45 | .input-card {
46 | width: auto;
47 | margin-bottom: 2em;
48 | }
49 |
50 | .textarea-full-width {
51 | width: 100%;
52 | textarea {
53 | height: 20vh;
54 | }
55 | }
56 |
57 | ::ng-deep {
58 | .mdc-text-field--filled {
59 | background-color: transparent !important;
60 | }
61 | .mat-mdc-form-field-focus-overlay {
62 | background-color: transparent !important;
63 | }
64 | /* TODO(mdc-migration): The following rule targets internal classes of form-field that may no longer apply for the MDC version. */
65 | .mat-mdc-text-field-wrapper {
66 | margin-bottom: -1.25em;
67 | }
68 | /* TODO(mdc-migration): The following rule targets internal classes of form-field that may no longer apply for the MDC version. */
69 | .mdc-floating-label {
70 | color: rgba(#fad02c, 0.8) !important;
71 | }
72 | /* TODO(mdc-migration): The following rule targets internal classes of form-field that may no longer apply for the MDC version. */
73 | .mat-focused .mdc-floating-label {
74 | color: #fad02c !important;
75 | }
76 | /* TODO(mdc-migration): The following rule targets internal classes of form-field that may no longer apply for the MDC version. */
77 | .mdc-line-ripple {
78 | background-color: #fad02c !important;
79 | }
80 |
81 | .mat-mdc-form-field.mat-accent .mat-mdc-input-element {
82 | caret-color: #fad02c;
83 | }
84 |
85 | .mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__input {
86 | color: currentcolor;
87 | }
88 | }
89 |
90 | .results-card {
91 | margin-right: 2em;
92 | cursor: pointer;
93 | }
94 |
--------------------------------------------------------------------------------
/src/app/helper/components/year-selection/year-selection.component.html:
--------------------------------------------------------------------------------
1 |
7 |
8 | {{ year }}
9 | Days: {{ getDays(year) }} / 25
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/app/helper/components/year-selection/year-selection.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex-flow: row wrap;
4 | mat-card {
5 | margin: 2em;
6 | cursor: pointer;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/helper/components/year-selection/year-selection.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import {
3 | AvailableSolutions,
4 | SolutionsCollectorService,
5 | } from '../../services/solutions-collector.service';
6 |
7 | @Component({
8 | selector: 'aoc-year-selection',
9 | templateUrl: './year-selection.component.html',
10 | styleUrls: ['./year-selection.component.scss'],
11 | })
12 | export class YearSelectionComponent implements OnInit {
13 | availableYears: number[] = [];
14 | availableSolutions: AvailableSolutions = {};
15 | constructor(private solutionsCollectorService: SolutionsCollectorService) {}
16 |
17 | ngOnInit() {
18 | this.solutionsCollectorService
19 | .getAvailableYearsObservable()
20 | .subscribe((years) => (this.availableYears = years));
21 | this.solutionsCollectorService
22 | .getAvailableSolutionsObservable()
23 | .subscribe((solutions) => (this.availableSolutions = solutions));
24 | }
25 |
26 | getDays(year: number): number {
27 | return Object.keys(this.availableSolutions[year]).length;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/helper/helper.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { HttpClientModule } from '@angular/common/http';
4 | import { ClipboardModule } from '@angular/cdk/clipboard';
5 | import { MatButtonModule } from '@angular/material/button';
6 | import { MatCardModule } from '@angular/material/card';
7 | import { MatInputModule } from '@angular/material/input';
8 | import { MatFormFieldModule } from '@angular/material/form-field';
9 | import { MatSnackBarModule } from '@angular/material/snack-bar';
10 | import { MatProgressBarModule } from '@angular/material/progress-bar';
11 |
12 | import { CanActivateDay } from './activate-route-guards/can-activate-day';
13 | import { DaySelectionComponent } from './components/day-selection/day-selection.component';
14 | import { YearSelectionComponent } from './components/year-selection/year-selection.component';
15 | import { SolutionComponent } from './components/solution/solution.component';
16 | import { RouterModule } from '@angular/router';
17 | import { SolutionsCollectorService } from './services/solutions-collector.service';
18 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
19 | import { CanActivateYear } from './activate-route-guards/can-activate-year';
20 | import { PlotlyGraphComponent } from './components/plotly-graph/plotly-graph.component';
21 | import { ScriptsLoaderService } from './services/scripts-loader.service';
22 |
23 | import { PlotlyViaCDNModule } from 'angular-plotly.js';
24 | import { AnimatorComponent } from './components/animator/animator.component';
25 | import { MatSliderModule } from '@angular/material/slider';
26 |
27 | PlotlyViaCDNModule.setPlotlyVersion('2.16.1');
28 | PlotlyViaCDNModule.setPlotlyBundle(null);
29 |
30 | @NgModule({
31 | declarations: [
32 | SolutionComponent,
33 | DaySelectionComponent,
34 | YearSelectionComponent,
35 | PlotlyGraphComponent,
36 | AnimatorComponent,
37 | ],
38 | imports: [
39 | CommonModule,
40 | RouterModule,
41 | FormsModule,
42 | ReactiveFormsModule,
43 | HttpClientModule,
44 | PlotlyViaCDNModule,
45 | ClipboardModule,
46 | MatButtonModule,
47 | MatCardModule,
48 | MatInputModule,
49 | MatFormFieldModule,
50 | MatSnackBarModule,
51 | MatProgressBarModule,
52 | MatSliderModule,
53 | ],
54 | providers: [
55 | CanActivateYear,
56 | CanActivateDay,
57 | ScriptsLoaderService,
58 | SolutionsCollectorService,
59 | ],
60 | exports: [AnimatorComponent],
61 | })
62 | export class HelperModule {}
63 |
--------------------------------------------------------------------------------
/src/app/helper/services/base-solution.service.ts:
--------------------------------------------------------------------------------
1 | import { ISolutionService, PuzzleResult } from './isolution.service';
2 | import { SolutionsCollectorService } from './solutions-collector.service';
3 |
4 | export abstract class BaseSolutionService implements ISolutionService {
5 | protected constructor(
6 | protected solutionsCollectorService: SolutionsCollectorService,
7 | protected year: number,
8 | protected day: number,
9 | protected dayName: string,
10 | protected additionalInfo: string = ''
11 | ) {
12 | solutionsCollectorService.registerSolution(year, day, dayName, this, additionalInfo);
13 | }
14 | solvePart1(
15 | input: string
16 | ):
17 | | string
18 | | number
19 | | PuzzleResult
20 | | Promise
21 | | Promise
22 | | Promise {
23 | throw new Error('Method not implemented.');
24 | }
25 | solvePart2(
26 | input: string
27 | ):
28 | | string
29 | | number
30 | | PuzzleResult
31 | | Promise
32 | | Promise
33 | | Promise {
34 | throw new Error('Method not implemented.');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/app/helper/services/isolution.service.ts:
--------------------------------------------------------------------------------
1 | import { Type } from '@angular/core';
2 | import { BaseResultComponent } from '../components/base-result.component';
3 |
4 | export interface PuzzleResult {
5 | result: string | number;
6 | component: Type;
7 | componentData: any;
8 | }
9 | export interface ISolutionService {
10 | solvePart1(
11 | input: string
12 | ):
13 | | number
14 | | string
15 | | PuzzleResult
16 | | Promise
17 | | Promise
18 | | Promise;
19 | solvePart2(
20 | input: string
21 | ):
22 | | number
23 | | string
24 | | PuzzleResult
25 | | Promise
26 | | Promise
27 | | Promise;
28 | }
29 |
--------------------------------------------------------------------------------
/src/app/helper/services/scripts-loader.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | @Injectable({
4 | providedIn: 'root',
5 | })
6 | export class ScriptsLoaderService {
7 | private loadedScripts: string[] = [];
8 | constructor() {}
9 |
10 | loadScript(name: string, srcUrl: string) {
11 | return new Promise((resolve, reject) => {
12 | var script = document.getElementById(name);
13 | if (this.loadedScripts.includes(name) && script) {
14 | resolve({ script: name, loaded: true, status: 'Loaded' });
15 | } else {
16 | const script = document.createElement('script');
17 | script.type = 'text/javascript';
18 | script.id = name;
19 | script.src = srcUrl;
20 | script.onload = () => {
21 | this.loadedScripts.push(name);
22 | resolve({ script: name, loaded: true, status: 'Loaded' });
23 | };
24 | script.onerror = (error: any) =>
25 | resolve({ script: name, loaded: false, status: 'Loaded' });
26 | document.getElementsByTagName('head')[0].appendChild(script);
27 | }
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/app/helper/services/solutions-collector.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { BehaviorSubject, map, Observable } from 'rxjs';
3 | import { ISolutionService } from './isolution.service';
4 |
5 | export interface SolutionObject {
6 | dayName: string;
7 | additionalInfo: string;
8 | service: ISolutionService;
9 | }
10 |
11 | export interface AvailableSolutions {
12 | [year: number]: {
13 | [day: number]: SolutionObject;
14 | };
15 | }
16 |
17 | @Injectable({
18 | providedIn: 'root',
19 | })
20 | export class SolutionsCollectorService {
21 | static readonly startYear: number = 2015;
22 | private availableSolutions = new BehaviorSubject({});
23 |
24 | getAvailableSolutionsObservable(): Observable {
25 | return this.availableSolutions.asObservable();
26 | }
27 |
28 | getAvailableYearsObservable(): Observable {
29 | return this.availableSolutions
30 | .asObservable()
31 | .pipe(map((solutions) => Object.keys(solutions).map((k) => Number(k))));
32 | }
33 |
34 | getAvailableDaysObservable(year: number): Observable<[number, string][]> {
35 | return this.availableSolutions
36 | .asObservable()
37 | .pipe(
38 | map((solutions) =>
39 | year in solutions
40 | ? Object.keys(solutions[year]).map((k) => [
41 | Number(k),
42 | solutions[year][Number(k)].dayName,
43 | ])
44 | : []
45 | )
46 | );
47 | }
48 |
49 | constructor() {}
50 |
51 | registerSolution(
52 | year: number,
53 | day: number,
54 | dayName: string,
55 | service: ISolutionService,
56 | additionalInfo: string = ''
57 | ) {
58 | if (day < 1 || day > 25) {
59 | throw new Error(`Cannot register solution for day ${day}!`);
60 | }
61 | var solutionsObj = this.availableSolutions.value;
62 | if (!(year in solutionsObj)) {
63 | solutionsObj[year] = {};
64 | }
65 | if (day in solutionsObj) {
66 | throw new Error(
67 | `Solutions for Year ${year}, Day ${day} has already been registered!`
68 | );
69 | }
70 | solutionsObj[year][day] = { dayName, additionalInfo, service };
71 | this.availableSolutions.next(solutionsObj);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/chunk.ts:
--------------------------------------------------------------------------------
1 | export function chunk(input: any[], n: number): any[][] {
2 | return Array.from(Array(Math.ceil(input.length / n)), (_, i) =>
3 | input.slice(i * n, i * n + n)
4 | );
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/color-interpolate.ts:
--------------------------------------------------------------------------------
1 | export interface RgbColor {
2 | r: number;
3 | g: number;
4 | b: number;
5 | }
6 |
7 | export function getRgb(color: string): RgbColor {
8 | let [r, g, b] = color
9 | .replace('rgb(', '')
10 | .replace(')', '')
11 | .split(',')
12 | .map((str) => Number(str));
13 | return {
14 | r,
15 | g,
16 | b,
17 | };
18 | }
19 |
20 | export function colorInterpolate(
21 | colorA: string,
22 | colorB: string,
23 | intval: number
24 | ): string {
25 | const rgbA = getRgb(colorA),
26 | rgbB = getRgb(colorB);
27 | const interpolatedColor: RgbColor = {
28 | r: rgbA.r * (1 - intval) + rgbB.r * intval,
29 | g: rgbA.g * (1 - intval) + rgbB.g * intval,
30 | b: rgbA.b * (1 - intval) + rgbB.b * intval,
31 | };
32 | return `rgb( ${interpolatedColor.r}, ${interpolatedColor.g}, ${interpolatedColor.b})`;
33 | }
34 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/deque.ts:
--------------------------------------------------------------------------------
1 | //Modified https://gist.github.com/Youka/e28beeb31f585ac9b9532636cadbdb8d
2 |
3 | // Linked data structure part
4 | interface DequeNode {
5 | previous?: DequeNode;
6 | value: T;
7 | next?: DequeNode;
8 | }
9 | // Double-ended queue structure
10 | export class Deque {
11 | private first?: DequeNode = undefined;
12 | private last?: DequeNode = undefined;
13 | private size: number = 0;
14 |
15 | public get length(): number {
16 | return this.size;
17 | }
18 | public get array(): T[] {
19 | var result: T[] = [];
20 | var current = this.first;
21 | while (current !== undefined) {
22 | result.push(current.value);
23 | current = current.next;
24 | }
25 | return result;
26 | }
27 | public pushBack(value: T) {
28 | // Update last
29 | const last = this.last;
30 | this.last = { previous: last, value: value, next: undefined };
31 | if (last !== undefined) last.next = this.last;
32 | // Update first
33 | if (this.first === undefined) this.first = this.last;
34 | // Update size
35 | this.size++;
36 | // Return new size
37 | return this.size;
38 | }
39 | public pushFront(value: T) {
40 | // Update first
41 | const first = this.first;
42 | this.first = { previous: undefined, value: value, next: first };
43 | if (first !== undefined) first.previous = this.first;
44 | // Update last
45 | if (this.last === undefined) this.last = this.first;
46 | // Update size
47 | this.size++;
48 | // Return new size
49 | return this.size;
50 | }
51 |
52 | public popBack() {
53 | // Check possibility
54 | if (this.size === 0) return undefined;
55 | // Update last
56 | const entry = this.last;
57 | this.last = entry!.previous;
58 | if (this.last !== undefined) this.last.next = undefined;
59 | // Update first
60 | if (this.first === entry) this.first = undefined;
61 | // Update size
62 | this.size--;
63 | // Return value of removed entry
64 | return entry!.value;
65 | }
66 | public popFront() {
67 | // Check possibility
68 | if (this.size === 0) return undefined;
69 | // Update first
70 | const entry = this.first;
71 | this.first = entry!.next;
72 | if (this.first !== undefined) this.first.previous = undefined;
73 | // Update last
74 | if (this.last === entry) this.last = undefined;
75 | // Update size
76 | this.size--;
77 | // Return value of removed entry
78 | return entry!.value;
79 | }
80 | public rotate(n: number) {
81 | if (this.size > 0) {
82 | var rotateForward = Math.sign(n) > 0;
83 | for (let i = 0; i < Math.abs(n); i++) {
84 | if (rotateForward) {
85 | this.pushBack(this.popFront()!);
86 | } else {
87 | this.pushFront(this.popBack()!);
88 | }
89 | }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/distances.ts:
--------------------------------------------------------------------------------
1 | import { Point2D, Point3D } from './point';
2 |
3 | export function euclidean2D(a: Point2D, b: Point2D): number {
4 | return Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
5 | }
6 |
7 | export function euclidean3D(a: Point3D, b: Point3D): number {
8 | return Math.sqrt(
9 | Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2) + Math.pow(b.z - a.z, 2)
10 | );
11 | }
12 |
13 | export function manhattan2D(a: Point2D, b: Point2D): number {
14 | return Math.abs(b.x - a.x) + Math.abs(b.y - a.y);
15 | }
16 |
17 | export function manhattan3D(a: Point3D, b: Point3D): number {
18 | return Math.abs(b.x - a.x) + Math.abs(b.y - a.y) + Math.abs(b.z - a.z);
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/extensions.ts:
--------------------------------------------------------------------------------
1 | import { chunk } from './chunk';
2 | import { multiplyNumbers } from './product';
3 | import { sumNumbers } from './sum';
4 |
5 | declare global {
6 | interface Array {
7 | sum(): number;
8 | product(): number;
9 | }
10 | }
11 |
12 | Array.prototype.sum = function (): number {
13 | return sumNumbers(this);
14 | };
15 |
16 | Array.prototype.product = function (): number {
17 | return multiplyNumbers(this);
18 | };
19 |
20 | declare global {
21 | interface Array {
22 | chunk(n: number): Array>;
23 | }
24 | }
25 |
26 | Array.prototype.chunk = function (n: number): Array> {
27 | return chunk(this, n);
28 | };
29 |
30 | declare global {
31 | interface ArrayConstructor {
32 | range(start: number, end: number): number[];
33 | }
34 | }
35 |
36 | Array.range = (start, end) =>
37 | Array.from({ length: end - start }, (v, k) => k + start);
38 |
39 | declare global {
40 | interface Array {
41 | findLast(
42 | predicate: (value: T, index: number, obj: T[]) => unknown,
43 | thisArg?: any
44 | ): T | undefined;
45 | findLastIndex(
46 | predicate: (value: T, index: number, obj: T[]) => unknown,
47 | thisArg?: any
48 | ): number;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/gcd.ts:
--------------------------------------------------------------------------------
1 | export function gcd(a: number, b: number): number {
2 | while (b != 0) {
3 | var x = b;
4 | b = a % b;
5 | a = x;
6 | }
7 | return a;
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/global-counter.ts:
--------------------------------------------------------------------------------
1 | export interface GlobalCounter {
2 | value: number;
3 | higherValue: number;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/is-number.ts:
--------------------------------------------------------------------------------
1 | export function isNumber(value: string | number): boolean {
2 | return value != null && value !== '' && !isNaN(Number(value.toString()));
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/lcm.ts:
--------------------------------------------------------------------------------
1 | export function lcm(a: number, b: number): number {
2 | var greater = a > b ? a : b;
3 |
4 | while (true) {
5 | if (greater % a == 0 && greater % b == 0) {
6 | return greater;
7 | }
8 | greater += 1;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/linked-list.ts:
--------------------------------------------------------------------------------
1 | export interface LinkedListNode {
2 | previous?: LinkedListNode;
3 | value: T;
4 | next?: LinkedListNode;
5 | }
6 |
7 | export function insertNode(value: T, last?: LinkedListNode) {
8 | let p: LinkedListNode = { value };
9 |
10 | if (last === undefined) {
11 | p.previous = p;
12 | p.next = p;
13 | } else {
14 | p.next = last.next;
15 | p.previous = last;
16 | last.next!.previous = p;
17 | last.next = p;
18 | }
19 | return p;
20 | }
21 |
22 | export function removeNode(p: LinkedListNode) {
23 | p.next!.previous = p.previous;
24 | p.previous!.next = p.next;
25 | }
26 |
27 | export function findNode(
28 | p: LinkedListNode,
29 | value: T
30 | ): LinkedListNode | undefined {
31 | var currentNode = p;
32 | do {
33 | if (currentNode.value === value) {
34 | return currentNode;
35 | }
36 | currentNode = currentNode.next!;
37 | } while (currentNode !== p);
38 | return;
39 | }
40 |
41 | export function swapWithNext(p: LinkedListNode) {
42 | var previous = p.previous!;
43 | var neighbour = p.next!;
44 | var next = neighbour.next!;
45 |
46 | previous.next = neighbour;
47 |
48 | neighbour.previous = previous;
49 | neighbour.next = p;
50 |
51 | p.previous = neighbour;
52 | p.next = next;
53 |
54 | next.previous = p;
55 |
56 | return p;
57 | }
58 |
59 | export function swapWithPrevious(p: LinkedListNode) {
60 | var next = p.next!;
61 | var neighbour = p.previous!;
62 | var previous = neighbour.previous!;
63 |
64 | next.previous = neighbour;
65 |
66 | neighbour.next = next;
67 | neighbour.previous = p;
68 |
69 | p.next = neighbour;
70 | p.previous = previous;
71 |
72 | previous.next = p;
73 |
74 | return p;
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/mod.ts:
--------------------------------------------------------------------------------
1 | export function mod(n: number, m: number) {
2 | return ((n % m) + m) % m;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/normalize.ts:
--------------------------------------------------------------------------------
1 | export function normalize(
2 | val: number,
3 | in_min: number,
4 | in_max: number,
5 | out_min: number,
6 | out_max: number
7 | ) {
8 | return ((val - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min;
9 | }
10 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/ocr.ts:
--------------------------------------------------------------------------------
1 | import { ScriptsLoaderService } from '../services/scripts-loader.service';
2 |
3 | declare let Tesseract: any;
4 |
5 | export async function OCR(
6 | x: number[],
7 | y: number[],
8 | z: number[],
9 | scriptsLoaderService: ScriptsLoaderService
10 | ): Promise {
11 | var maxX = Math.max(...x);
12 | var maxY = Math.max(...y);
13 |
14 | var canvas = document.createElement('canvas');
15 | let ctx = canvas.getContext('2d');
16 | let image = document.getElementById('source');
17 | const magnifier = 5;
18 | canvas.width = magnifier * (maxX + 3);
19 | canvas.height = magnifier * (maxY + 3);
20 | for (let i = 0; i < x.length; i++) {
21 | if (z[i] > 0) {
22 | ctx?.fillRect(
23 | (x[i] + 1) * magnifier,
24 | (y[i] + 1) * magnifier,
25 | magnifier,
26 | magnifier
27 | );
28 | }
29 | }
30 | const data = canvas.toDataURL();
31 | return scriptsLoaderService
32 | .loadScript(
33 | 'Tesseract',
34 | 'https://unpkg.com/tesseract.js@v2.1.0/dist/tesseract.min.js'
35 | )
36 | .then((res) => {
37 | return Tesseract.recognize(data, 'eng', {}).then((data: any) => {
38 | return data.data.text;
39 | });
40 | });
41 | }
42 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/parse-first-line-into-numbers.ts:
--------------------------------------------------------------------------------
1 | import { splitIntoLines } from './split-into-lines';
2 |
3 | export function parseFirstLineIntoNumbers(input: string): number[] {
4 | return splitIntoLines(input)[0].split(',').map(Number);
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/parse-into-2d-numbers-array.ts:
--------------------------------------------------------------------------------
1 | import { splitIntoLines } from './split-into-lines';
2 |
3 | export function parseInto2DNumbersArray(input: string): number[][] {
4 | return splitIntoLines(input).map((line) => line.split('').map(Number));
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/parse-into-numbers.ts:
--------------------------------------------------------------------------------
1 | import { splitIntoLines } from './split-into-lines';
2 |
3 | export function parseIntoNumbers(input: string): number[] {
4 | return splitIntoLines(input)
5 | .filter((line) => line.trim().length > 0)
6 | .map((line) => Number(line.trim()))
7 | .filter((num) => !isNaN(num));
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/point.ts:
--------------------------------------------------------------------------------
1 | export interface Point2D {
2 | x: number;
3 | y: number;
4 | }
5 |
6 | export interface Point3D extends Point2D {
7 | z: number;
8 | }
9 |
10 | export function points2DEqual(a: Point2D, b: Point2D): boolean {
11 | return a.x == b.x && a.y == b.y;
12 | }
13 |
14 | export function points3DEqual(a: Point3D, b: Point3D): boolean {
15 | return a.x == b.x && a.y == b.y && a.z == b.z;
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/product.ts:
--------------------------------------------------------------------------------
1 | export function multiplyNumbers(input: number[]): number {
2 | if (input.length == 0) {
3 | return 0;
4 | }
5 | return input.reduce((a, b) => a * b);
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/queue.ts:
--------------------------------------------------------------------------------
1 | export class Queue {
2 | protected _store: T[] = [];
3 | get store(): T[] {
4 | return this._store;
5 | }
6 | isEmpty(): boolean {
7 | return this._store.length == 0;
8 | }
9 | enqueue(val: T) {
10 | this._store.push(val);
11 | }
12 | dequeue(): T | undefined {
13 | return this._store.shift();
14 | }
15 | clear(): void {
16 | this._store = [];
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/split-into-lines.ts:
--------------------------------------------------------------------------------
1 | export function splitIntoLines(input: string, trim: boolean = false): string[] {
2 | var lines = input.split('\n');
3 | if (trim) {
4 | lines = lines.map((l) => l.trim());
5 | }
6 | if (lines[lines.length - 1].trim().length == 0) {
7 | lines = lines.slice(0, lines.length - 1);
8 | }
9 | return lines;
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/stack.ts:
--------------------------------------------------------------------------------
1 | export class Stack {
2 | constructor(
3 | private capacity: number = Infinity,
4 | protected _store: T[] = []
5 | ) {}
6 |
7 | get store(): T[] {
8 | return this._store;
9 | }
10 |
11 | push(item: T): void {
12 | if (this.size() === this.capacity) {
13 | throw Error('Stack has reached max capacity, you cannot add more items');
14 | }
15 | this._store.push(item);
16 | }
17 |
18 | pop(): T | undefined {
19 | return this._store.pop();
20 | }
21 |
22 | peek(): T | undefined {
23 | return this._store[this.size() - 1];
24 | }
25 |
26 | size(): number {
27 | return this._store.length;
28 | }
29 |
30 | copy(): Stack {
31 | return new Stack(this.capacity, Object.assign([], this._store));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/sum.ts:
--------------------------------------------------------------------------------
1 | export function sumNumbers(input: number[]): number {
2 | if (input.length == 0) {
3 | return 0;
4 | }
5 | return input.reduce((a, b) => a + b);
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/helper/util-functions/two-way-map.ts:
--------------------------------------------------------------------------------
1 | export class TwoWayMap {
2 | map: Map;
3 | reverseMap: Map;
4 | constructor() {
5 | this.map = new Map();
6 | this.reverseMap = new Map();
7 | }
8 | get(key: K) {
9 | return this.map.get(key);
10 | }
11 | set(key: K, value: V) {
12 | this.map.set(key, value);
13 | this.reverseMap.set(value, key);
14 | }
15 | delete(key: K) {
16 | var value = this.map.get(key)!;
17 | this.map.delete(key);
18 | this.reverseMap.delete(value);
19 | }
20 | revGet(key: V) {
21 | return this.reverseMap.get(key);
22 | }
23 | values() {
24 | return [...this.reverseMap.keys()];
25 | }
26 | }
27 |
28 | export class TwoWayNumberMap extends TwoWayMap {
29 | private static eps: number = 0.00005;
30 | override set(key: number, value: number) {
31 | var alteredValue = value;
32 | while (this.reverseMap.has(alteredValue)) {
33 | alteredValue -= TwoWayNumberMap.eps;
34 | }
35 | this.map.set(key, alteredValue);
36 | this.reverseMap.set(alteredValue, key);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/amphipods-room-visualizer/amphipods-room-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
11 |
20 |
21 |
22 | Current step: {{ currentStateIdx }}
23 | Total cost: {{ currentCost }}
24 |
25 |
26 |
32 |
39 | {{ room.occupant }}
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/amphipods-room-visualizer/amphipods-room-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | .room-grid {
2 | margin-top: 0.5em;
3 | display: grid;
4 | grid-template-columns: repeat(var(--col), 1.5em);
5 | grid-template-rows: repeat(var(--row), 1.5em);
6 |
7 | .cell {
8 | grid-column-end: span 1;
9 | grid-row-end: span 1;
10 | height: 1.5em;
11 | width: 1.5em;
12 | display: flex;
13 | justify-content: center;
14 |
15 | &.border-cell {
16 | background-color: rgba(#fad02c, 0.5);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/amphipods-room-visualizer/amphipods-room-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, HostBinding, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { Point2D } from 'src/app/helper/util-functions/point';
4 | import { AmphipodRoomField } from '../../day23.service';
5 |
6 | @Component({
7 | selector: 'aoc-amphipods-room-visualizer',
8 | templateUrl: './amphipods-room-visualizer.component.html',
9 | styleUrls: ['./amphipods-room-visualizer.component.scss'],
10 | })
11 | export class AmphipodsRoomVisualizerComponent
12 | extends BaseResultComponent
13 | implements OnInit
14 | {
15 | states: AmphipodRoomField[][] = [];
16 | border: Point2D[] = [];
17 | costs: number[] = [];
18 | currentStateIdx: number = 0;
19 | minX: number = 0;
20 | maxX: number = 0;
21 | minY: number = 0;
22 | maxY: number = 0;
23 |
24 | @HostBinding('style.--col')
25 | get col(): number {
26 | return this.maxX - this.minX;
27 | }
28 |
29 | @HostBinding('style.--row')
30 | get row(): number {
31 | return this.maxY - this.minY;
32 | }
33 |
34 | ngOnInit(): void {
35 | this.states = this.data.states as AmphipodRoomField[][];
36 | this.border = this.data.border as Point2D[];
37 | this.costs = this.data.costs as number[];
38 | this.currentStateIdx = 0;
39 | this.minX = Math.min(...this.border.map((p) => p.x));
40 | this.maxX = Math.max(...this.border.map((p) => p.x));
41 | this.minY = Math.min(...this.border.map((p) => p.y));
42 | this.maxY = Math.max(...this.border.map((p) => p.y));
43 | }
44 |
45 | nextStep() {
46 | this.currentStateIdx++;
47 | }
48 |
49 | prevStep() {
50 | this.currentStateIdx--;
51 | }
52 |
53 | get currentState(): AmphipodRoomField[] {
54 | return this.states[this.currentStateIdx];
55 | }
56 |
57 | get currentCost(): number {
58 | return this.costs[this.currentStateIdx];
59 | }
60 |
61 | get currentMoving(): number | undefined {
62 | if (this.currentStateIdx == this.states.length - 1) {
63 | return undefined;
64 | }
65 | var currentState = this.states[this.currentStateIdx];
66 | var nextState = this.states[this.currentStateIdx + 1];
67 | var result = 0;
68 | currentState.forEach((f, idx) => {
69 | if (currentState[idx].occupant && !nextState[idx].occupant) {
70 | result = idx;
71 | }
72 | });
73 | return result;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/arithmetic-logic-unit-visualizer/arithmetic-logic-unit-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
11 |
20 |
21 |
22 |
23 | NOMAD version:
24 | {{ digit }}
29 |
30 |
31 |
32 | {{ instruction[0] }}
33 |
34 | [w: {{ instruction[1].get("w") }}, x: {{ instruction[1].get("x") }}, y:
35 | {{ instruction[1].get("y") }}, z: {{ instruction[1].get("z") }}]
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/arithmetic-logic-unit-visualizer/arithmetic-logic-unit-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | .nomad-number {
2 | font-size: 1.5rem;
3 | margin-bottom: 0.5em;
4 | }
5 |
6 | .nomad-instructions {
7 | display: grid;
8 | width: fit-content;
9 | grid-template-columns: auto auto;
10 | grid-column-gap: 0.5em;
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/arithmetic-logic-unit-visualizer/arithmetic-logic-unit-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-arithmetic-logic-unit-visualizer',
6 | templateUrl: './arithmetic-logic-unit-visualizer.component.html',
7 | styleUrls: ['./arithmetic-logic-unit-visualizer.component.scss'],
8 | })
9 | export class ArithmeticLogicUnitVisualizerComponent
10 | extends BaseResultComponent
11 | implements OnInit
12 | {
13 | currentDigitIdx: number = 0;
14 | instructions: [string, Map][][] = [];
15 | number!: string;
16 | ngOnInit(): void {
17 | this.number = this.data.number as string;
18 | this.instructions = this.data.instructions as [
19 | string,
20 | Map
21 | ][][];
22 | }
23 |
24 | nextStep() {
25 | this.currentDigitIdx++;
26 | }
27 |
28 | prevStep() {
29 | this.currentDigitIdx--;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/bingo-visualizer/bingo-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
Numbers:
13 |
18 | {{ number }}
19 |
20 |
21 |
22 |
23 |
28 |
36 | {{ number }}
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/bingo-visualizer/bingo-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | .flex-row {
2 | display: flex;
3 | flex-flow: row wrap;
4 | }
5 |
6 | .number-cell {
7 | height: 1.5em;
8 | width: 1.5em;
9 | display: flex;
10 | justify-content: center;
11 | border-radius: 0.25em;
12 | margin: 0.1em;
13 | }
14 |
15 | .board {
16 | margin: 0.75em;
17 | display: grid;
18 | grid-template-columns: repeat(5, auto);
19 | border: rgba(#fff, 0.1) solid 2px;
20 |
21 | &.won {
22 | border: #fad02c solid 2px;
23 | box-shadow: 0 0 1em #fad02c;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/bingo-visualizer/bingo-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { normalize } from 'src/app/helper/util-functions/normalize';
4 |
5 | @Component({
6 | selector: 'aoc-bingo-visualizer',
7 | templateUrl: './bingo-visualizer.component.html',
8 | styleUrls: ['./bingo-visualizer.component.scss'],
9 | })
10 | export class BingoVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit
13 | {
14 | boards!: number[][][];
15 | numbers!: number[];
16 | visualizeCounter: number = 0;
17 | wonBoards!: number[];
18 | visualizing: boolean = false;
19 | ngOnInit(): void {
20 | var fullBoards = this.data.boards as [number, boolean][][][];
21 | this.boards = fullBoards.map((board) =>
22 | board.map((row) => row.map((tuple) => tuple[0]))
23 | );
24 | this.numbers = this.data.numbers as number[];
25 | this.visualizeCounter = this.numbers.length;
26 | this.wonBoards = this.data.wonBoards;
27 | }
28 |
29 | getNumberStyle(n: number): string {
30 | var idx = this.numbers
31 | .slice(0, this.visualizeCounter)
32 | .findIndex((num) => num == n);
33 | if (idx >= 0) {
34 | var value = normalize(idx, 0, this.numbers.length, 0.25, 1);
35 | return `rgba(250, 208, 44, ${value})`;
36 | }
37 | return 'transparent';
38 | }
39 | startVisualization() {
40 | this.visualizing = true;
41 | this.visualizeCounter = 0;
42 | this.loop();
43 | }
44 |
45 | private loop() {
46 | setTimeout(() => {
47 | this.visualizeCounter++;
48 | if (this.visualizeCounter < this.numbers.length) {
49 | this.loop();
50 | } else {
51 | this.visualizing = false;
52 | }
53 | }, 100);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/bits-visualizer/bits-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0" class="monospace">
4 | {{
5 | separator == 0 ? "⠀⠀" : "│⠀"
6 | }}
7 | ├
8 | └
9 |
10 | 0">⠀
11 |
12 | Version:
14 | {{
15 | packet.packetBits?.slice(0, 3)
16 | }}
17 | ({{ packet.version }})
20 | Type ID: {{ packet.packetBits?.slice(3, 6) }} ({{
22 | packet.typeId
23 | }})
25 |
26 | Length type ID: {{ packet.lengthId }}
29 |
30 | Subpackets total length:
32 | {{ packet.packetBits?.slice(7, 23) }} ({{
33 | packet.lengthNumber
34 | }})
36 |
37 |
38 | Number of subpackets:
40 | {{ packet.packetBits?.slice(7, 18) }} ({{
41 | packet.lengthNumber
42 | }})
44 |
45 |
46 |
47 |
48 |
49 | Operator: {{ packet.packetBits?.slice(3, 6) }} ({{ getOperator(packet.typeId) }})
55 | Final value:
57 | {{ packet.value }}
59 |
60 |
61 | Literal value:
63 | {{ c }}
71 | ({{ packet.value }})
74 |
75 |
76 |
77 |
78 |
79 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/bits-visualizer/bits-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | width: 100%;
3 | display: block;
4 | margin-top: -0.4em;
5 |
6 | span {
7 | display: inline-block;
8 | line-height: 1em;
9 | }
10 |
11 | .bits-row {
12 | margin-right: 0.5em;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/bits-visualizer/bits-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { Packet } from '../../day16.service';
4 |
5 | @Component({
6 | selector: 'aoc-bits-visualizer',
7 | templateUrl: './bits-visualizer.component.html',
8 | styleUrls: ['./bits-visualizer.component.scss'],
9 | })
10 | export class BitsVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit
13 | {
14 | @Input() packet!: Packet;
15 | @Input() depth: number = 0;
16 | @Input() separators: number[] = [];
17 | @Input() isChild: boolean = false;
18 | @Input() isLast: boolean = true;
19 | @Input() showValues: boolean = false;
20 |
21 | ngOnInit(): void {
22 | if (this.data) {
23 | this.packet = this.data.packet as Packet;
24 | this.showValues = this.data.showValues as boolean;
25 | }
26 | }
27 |
28 | getOperator(typeId: number): string {
29 | switch (typeId) {
30 | case 0:
31 | return '+';
32 | case 1:
33 | return '×';
34 | case 2:
35 | return 'Min';
36 | case 3:
37 | return 'Max';
38 | case 5:
39 | return '>';
40 | case 6:
41 | return '<';
42 | case 7:
43 | return '=';
44 | default:
45 | return '';
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/caves-visualizer/caves-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/caves-visualizer/caves-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | .network {
2 | height: 800px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/caves-visualizer/caves-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { ScriptsLoaderService } from 'src/app/helper/services/scripts-loader.service';
4 |
5 | declare let vis: any;
6 |
7 | @Component({
8 | selector: 'aoc-caves-visualizer',
9 | templateUrl: './caves-visualizer.component.html',
10 | styleUrls: ['./caves-visualizer.component.scss'],
11 | })
12 | export class CavesVisualizerComponent
13 | extends BaseResultComponent
14 | implements OnInit
15 | {
16 | networkId!: string;
17 | visLoaded: boolean = false;
18 | constructor(private scripts: ScriptsLoaderService) {
19 | super();
20 | this.networkId = (Math.random() + 1).toString(36).substring(2);
21 | }
22 |
23 | ngOnInit(): void {
24 | var sources: number[] = this.data.sources as number[];
25 | var targets: number[] = this.data.targets as number[];
26 | var values: number[] = this.data.values as number[];
27 | var labels: string[] = this.data.labels as string[];
28 | var maxValue = Math.max(...values);
29 | this.scripts
30 | .loadScript(
31 | 'VisNetwork',
32 | 'https://unpkg.com/vis-network/standalone/umd/vis-network.min.js'
33 | )
34 | .then(() => {
35 | var nodes = new vis.DataSet(
36 | labels.map((l, idx) => {
37 | return { id: idx, label: l };
38 | })
39 | );
40 | var edges = new vis.DataSet(
41 | sources.map((s, idx) => {
42 | return {
43 | from: s,
44 | to: targets[idx],
45 | value: values[idx] / maxValue,
46 | arrows: 'to',
47 | color: '#fad02c',
48 | };
49 | })
50 | );
51 |
52 | var container = document.getElementById(this.networkId);
53 |
54 | // provide the data in the vis format
55 | var data = {
56 | nodes: nodes,
57 | edges: edges,
58 | };
59 | var options = {
60 | physics: {
61 | barnesHut: {
62 | springConstant: 0,
63 | avoidOverlap: 0.2,
64 | },
65 | },
66 | };
67 |
68 | // initialize your network!
69 | var network = new vis.Network(container, data, options);
70 | // network.stabilize();
71 | });
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/ocean-trench-visualizer/ocean-trench-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
10 |
11 | Current step: {{ currentIdx }}
12 | Lit pixels: {{ litPixels }}
13 |
14 |
15 |
![]()
16 |
17 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/ocean-trench-visualizer/ocean-trench-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 | .flex-row {
6 | display: flex;
7 | flex-flow: row wrap;
8 | }
9 | .grid-wrapper {
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/ocean-trench-visualizer/ocean-trench-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-ocean-trench-visualizer',
6 | templateUrl: './ocean-trench-visualizer.component.html',
7 | styleUrls: ['./ocean-trench-visualizer.component.scss'],
8 | })
9 | export class OceanTrenchVisualizerComponent
10 | extends BaseResultComponent
11 | implements OnInit, AfterViewInit
12 | {
13 | images: number[][][] = [];
14 | currentIdx: number = 0;
15 | visualizing: boolean = false;
16 | squareWidth: number = 5;
17 |
18 | constructor(private el: ElementRef) {
19 | super();
20 | }
21 |
22 | get image(): number[][] {
23 | return this.images[this.currentIdx];
24 | }
25 |
26 | get litPixels(): number {
27 | return this.image.flat().filter((d) => d == 1).length;
28 | }
29 |
30 | get imageWidth(): number {
31 | return this.image.length;
32 | }
33 |
34 | get finalWidth(): number {
35 | return this.images.slice(-1)[0].length;
36 | }
37 |
38 | get imageCanvas(): string {
39 | var imageArray = this.image;
40 |
41 | var canvas = document.createElement('canvas');
42 | let ctx = canvas.getContext('2d');
43 | const magnifier = this.squareWidth;
44 | canvas.width = magnifier * this.imageWidth;
45 | canvas.height = magnifier * this.imageWidth;
46 | ctx!.fillStyle = '#fad02c';
47 | imageArray.forEach((row, y) => {
48 | row.forEach((val, x) => {
49 | if (val) {
50 | ctx!.fillRect(x * magnifier, y * magnifier, magnifier, magnifier);
51 | }
52 | });
53 | });
54 | const data = canvas.toDataURL();
55 | return data;
56 | }
57 |
58 | ngOnInit(): void {
59 | this.images = this.data.images as number[][][];
60 | this.currentIdx = this.images.length - 1;
61 | this.currentIdx = 0;
62 | }
63 |
64 | ngAfterViewInit(): void {
65 | this.squareWidth =
66 | this.el.nativeElement.offsetWidth / (3 * this.finalWidth);
67 | }
68 |
69 | startVisualization() {
70 | this.visualizing = true;
71 | this.currentIdx = 0;
72 | this.loop();
73 | }
74 |
75 | private loop() {
76 | setTimeout(() => {
77 | this.currentIdx++;
78 | if (this.currentIdx < this.images.length - 1) {
79 | this.loop();
80 | } else {
81 | this.visualizing = false;
82 | }
83 | }, 100);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/octopus-flashes-visualizer/octopus-flashes-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
10 |
11 | Current step: {{ currentIdx }}
12 | Flashes sum: {{ flashedAmount }}
13 |
14 |
15 |
20 | {{ number }}
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/octopus-flashes-visualizer/octopus-flashes-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | .number-cell {
2 | height: 1.5em;
3 | width: 1.5em;
4 | display: flex;
5 | justify-content: center;
6 | border-radius: 0.25em;
7 | margin: 0.1em;
8 | }
9 |
10 | .flex-row {
11 | display: flex;
12 | flex-flow: row wrap;
13 | }
14 |
15 | .grid {
16 | margin: 0.75em;
17 | display: grid;
18 | grid-template-columns: repeat(10, auto);
19 | width: fit-content;
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/octopus-flashes-visualizer/octopus-flashes-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-octopus-flashes-visualizer',
6 | templateUrl: './octopus-flashes-visualizer.component.html',
7 | styleUrls: ['./octopus-flashes-visualizer.component.scss'],
8 | })
9 | export class OctopusFlashesVisualizerComponent
10 | extends BaseResultComponent
11 | implements OnInit
12 | {
13 | snapshots: number[][][] = [];
14 | flashes: number[] = [];
15 | currentIdx: number = 0;
16 | visualizing: boolean = false;
17 |
18 | get snapshot(): number[][] {
19 | return this.snapshots[this.currentIdx];
20 | }
21 |
22 | get flashedAmount(): number {
23 | return this.currentIdx > 0
24 | ? this.flashes.slice(0, this.currentIdx).reduce((a, b) => a + b)
25 | : this.flashes[0];
26 | }
27 |
28 | ngOnInit(): void {
29 | this.snapshots = this.data.snapshots as number[][][];
30 | this.flashes = this.data.flashes as number[];
31 | this.currentIdx = this.snapshots.length - 1;
32 | }
33 |
34 | startVisualization() {
35 | this.visualizing = true;
36 | this.currentIdx = 0;
37 | this.loop();
38 | }
39 |
40 | private loop() {
41 | setTimeout(() => {
42 | this.currentIdx++;
43 | if (this.currentIdx < this.snapshots.length - 1) {
44 | this.loop();
45 | } else {
46 | this.visualizing = false;
47 | }
48 | }, 100);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/sea-cucumbers-visualizer/sea-cucumbers-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
10 |
11 | Current step: {{ currentIdx }}
12 |
13 |
14 |
![]()
15 |
16 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/sea-cucumbers-visualizer/sea-cucumbers-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 | .flex-row {
6 | display: flex;
7 | flex-flow: row wrap;
8 | }
9 | .grid-wrapper {
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/sea-cucumbers-visualizer/sea-cucumbers-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-sea-cucumbers-visualizer',
6 | templateUrl: './sea-cucumbers-visualizer.component.html',
7 | styleUrls: ['./sea-cucumbers-visualizer.component.scss'],
8 | })
9 | export class SeaCucumbersVisualizerComponent
10 | extends BaseResultComponent
11 | implements OnInit, AfterViewInit
12 | {
13 | areas: string[][][] = [];
14 | currentIdx: number = 0;
15 | visualizing: boolean = false;
16 | squareWidth: number = 5;
17 |
18 | constructor(private el: ElementRef) {
19 | super();
20 | }
21 |
22 | get area(): string[][] {
23 | return this.areas[this.currentIdx];
24 | }
25 |
26 | get imageWidth(): number {
27 | return this.area.length;
28 | }
29 |
30 | get imageCanvas(): string {
31 | var imageArray = this.area;
32 |
33 | var canvas = document.createElement('canvas');
34 | let ctx = canvas.getContext('2d');
35 | const magnifier = this.squareWidth;
36 | canvas.width = magnifier * this.imageWidth;
37 | canvas.height = magnifier * this.imageWidth;
38 | ctx!.fillStyle = '#fad02c';
39 | imageArray.forEach((row, y) => {
40 | row.forEach((val, x) => {
41 | if (val == '>' || val == 'v') {
42 | ctx!.fillStyle = val == '>' ? '#fad02c' : '#ffffff';
43 | ctx!.fillRect(x * magnifier, y * magnifier, magnifier, magnifier);
44 | }
45 | });
46 | });
47 | const data = canvas.toDataURL();
48 | return data;
49 | }
50 |
51 | ngOnInit(): void {
52 | this.areas = this.data.areas as string[][][];
53 | this.currentIdx = 0;
54 | }
55 |
56 | ngAfterViewInit(): void {
57 | this.squareWidth =
58 | this.el.nativeElement.offsetWidth / (3 * this.imageWidth);
59 | }
60 |
61 | startVisualization() {
62 | this.visualizing = true;
63 | this.currentIdx = 0;
64 | this.loop();
65 | }
66 |
67 | private loop() {
68 | setTimeout(() => {
69 | this.currentIdx++;
70 | if (this.currentIdx < this.areas.length - 1) {
71 | this.loop();
72 | } else {
73 | this.visualizing = false;
74 | }
75 | }, 100);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/seven-segments-display-visualizer/seven-segments-display-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
10 |
>
11 |
19 |
20 | ➔
21 |
32 | >
33 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/seven-segments-display-visualizer/seven-segments-display-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | .display-row {
2 | display: flex;
3 | flex-flow: row;
4 |
5 | .divider {
6 | display: flex;
7 | align-items: center;
8 | margin-left: 0.5em;
9 | margin-right: 0.5em;
10 | font-size: 2em;
11 | line-height: 1em;
12 | }
13 |
14 | .display-block {
15 | display: flex;
16 | flex-flow: column;
17 | width: fit-content;
18 | height: fit-content;
19 | margin: 0.25em;
20 |
21 | &.accented {
22 | filter: drop-shadow(0 0 2px #fad02c) drop-shadow(0 0 5px #fad02c);
23 | }
24 |
25 | .display-block-part {
26 | height: 1em;
27 | width: 1em;
28 | box-sizing: border-box;
29 | border-color: #fad02c;
30 | border-style: solid;
31 | border-width: 0;
32 |
33 | &:nth-child(1) {
34 | border-top-left-radius: 2px;
35 | border-top-right-radius: 2px;
36 | }
37 |
38 | &:nth-child(2) {
39 | border-bottom-left-radius: 2px;
40 | border-bottom-right-radius: 2px;
41 | }
42 |
43 | &.a:nth-child(1) {
44 | border-top-width: 2px;
45 | }
46 |
47 | &.b:nth-child(1),
48 | &.e:nth-child(2) {
49 | border-left-width: 2px;
50 | }
51 |
52 | &.c:nth-child(1),
53 | &.f:nth-child(2) {
54 | border-right-width: 2px;
55 | }
56 |
57 | &.d:nth-child(1) {
58 | border-bottom-width: 2px;
59 | }
60 |
61 | &.g:nth-child(2) {
62 | border-bottom-width: 2px;
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/seven-segments-display-visualizer/seven-segments-display-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { Display } from '../../day8.service';
4 |
5 | @Component({
6 | selector: 'aoc-seven-segments-display-visualizer',
7 | templateUrl: './seven-segments-display-visualizer.component.html',
8 | styleUrls: ['./seven-segments-display-visualizer.component.scss'],
9 | })
10 | export class SevenSegmentsDisplayVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit
13 | {
14 | inputDisplays!: Display[];
15 | decodedDisplays!: Display[];
16 | accentUniqueLengths: boolean = false;
17 | uniqueLenghts = [2, 3, 4, 7];
18 | ngOnInit(): void {
19 | this.inputDisplays = this.data.inputDisplays as Display[];
20 | this.decodedDisplays = (this.data.decodedDisplays ?? []) as Display[];
21 | this.accentUniqueLengths = this.data.accentUniqueLengths as boolean ?? false;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/snailfish-number-visualizer/snailfish-number-visualizer.component.html:
--------------------------------------------------------------------------------
1 | 0; else snailfish" class="accent-color">
2 |
3 |
12 |
21 |
30 |
43 |
44 |
45 | Animation speed: {{ interval }}ms
46 |
47 |
54 |
55 |
56 |
57 |
58 | Adding numbers:
59 |
63 | +
64 |
69 | Iterations: {{ iterations }} ({{ currentSnapshotIdx + 1 }}:
70 | {{ currentSnailfishIdx + 1 }})
71 |
72 |
73 |
80 |
81 |
82 |
83 | 0 ? 0.25 : 0"
85 | class="accent-color"
86 | [class.accent-glow]="isMarked"
87 | [class.non-glow]="!isMarked"
88 | >
89 | [
90 |
{{ currentSnailfish.x }}
93 |
99 | ,
100 |
{{ currentSnailfish.y }}
109 | ]
110 |
111 |
112 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/snailfish-number-visualizer/snailfish-number-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: inline-block;
3 | vertical-align: top;
4 | }
5 |
6 | .non-glow {
7 | text-shadow: none;
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/syntax-error-lines-visualizer/syntax-error-lines-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{ lines[i] }}
3 | {{ result }}
4 |
8 | {{ scores[i] }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/syntax-error-lines-visualizer/syntax-error-lines-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: grid;
3 | grid-template-columns: repeat(3, auto);
4 | width: fit-content;
5 | column-gap: 1em;
6 | }
7 | .flex-row {
8 | display: flex;
9 | flex-flow: row;
10 | }
11 |
12 | .monospace {
13 | font-family: monospace;
14 | display: flex;
15 | width: fit-content;
16 | align-items: center;
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/solutions2021/components/syntax-error-lines-visualizer/syntax-error-lines-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-syntax-error-lines-visualizer',
6 | templateUrl: './syntax-error-lines-visualizer.component.html',
7 | styleUrls: ['./syntax-error-lines-visualizer.component.scss'],
8 | })
9 | export class SyntaxErrorLinesVisualizerComponent
10 | extends BaseResultComponent
11 | implements OnInit
12 | {
13 | lines!: string[];
14 | results!: string[];
15 | scores!: number[];
16 | medianScore: number | undefined;
17 |
18 | ngOnInit(): void {
19 | this.lines = this.data.lines as string[];
20 | this.results = this.data.results as string[];
21 | this.scores = this.data.scores as number[];
22 | this.medianScore = this.data.medianScore as number;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/app/solutions2021/day1.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { parseIntoNumbers } from '../helper/util-functions/parse-into-numbers';
10 |
11 | @Injectable({
12 | providedIn: 'root',
13 | })
14 | export class Day1Service
15 | extends BaseSolutionService
16 | implements ISolutionService
17 | {
18 | constructor(solutionsCollectorService: SolutionsCollectorService) {
19 | super(solutionsCollectorService, 2021, 1, 'Sonar Sweep');
20 | }
21 | override solvePart1(input: string): PuzzleResult {
22 | var measurements = parseIntoNumbers(input);
23 | var increases = [];
24 | for (let i = 1; i < measurements.length; i++) {
25 | if (measurements[i - 1] < measurements[i]) {
26 | increases.push([i, measurements[i]]);
27 | }
28 | }
29 | return {
30 | result: increases.length,
31 | component: PlotlyGraphComponent,
32 | componentData: {
33 | graphData: [
34 | {
35 | x: measurements.map((val, idx) => idx),
36 | y: measurements,
37 | mode: 'lines',
38 | name: 'Measurements',
39 | line: {
40 | color: 'rgba(#ffffff, 0.8)',
41 | },
42 | },
43 | {
44 | x: increases.map((t) => t[0]),
45 | y: increases.map((t) => t[1]),
46 | mode: 'markers',
47 | name: 'Increases',
48 | marker: {
49 | color: '#fad02c',
50 | size: 2,
51 | },
52 | },
53 | ],
54 | graphLayout: {
55 | yaxis: { title: 'Depth', autorange: 'reversed' },
56 | xaxis: { title: 'Time' },
57 | },
58 | },
59 | };
60 | }
61 | override solvePart2(input: string): PuzzleResult {
62 | var measurements = parseIntoNumbers(input);
63 | var measurementsWindows = [];
64 | var increases = [];
65 | measurementsWindows.push([
66 | 2,
67 | measurements[0] + measurements[1] + measurements[2],
68 | ]);
69 | for (let i = 3; i < measurements.length; i++) {
70 | const window1 =
71 | measurements[i - 3] + measurements[i - 2] + measurements[i - 1];
72 | const window2 =
73 | measurements[i - 2] + measurements[i - 1] + measurements[i];
74 | measurementsWindows.push([i, window2]);
75 | if (window1 < window2) {
76 | increases.push([i, window2]);
77 | }
78 | }
79 | return {
80 | result: increases.length,
81 | component: PlotlyGraphComponent,
82 | componentData: {
83 | graphData: [
84 | {
85 | x: measurementsWindows.map((t) => t[0]),
86 | y: measurementsWindows.map((t) => t[1]),
87 | mode: 'lines',
88 | name: 'Measurements',
89 | line: {
90 | color: 'rgba(#ffffff, 0.8)',
91 | },
92 | },
93 | {
94 | x: increases.map((t) => t[0]),
95 | y: increases.map((t) => t[1]),
96 | mode: 'markers',
97 | name: 'Increases',
98 | marker: {
99 | color: 'rgb(#fad02c)',
100 | size: 2,
101 | },
102 | },
103 | ],
104 | graphLayout: { yaxis: { title: 'Depth', autorange: 'reversed' } },
105 | },
106 | };
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/app/solutions2021/day2.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { splitIntoLines } from '../helper/util-functions/split-into-lines';
10 |
11 | @Injectable({
12 | providedIn: 'root',
13 | })
14 | export class Day2Service
15 | extends BaseSolutionService
16 | implements ISolutionService
17 | {
18 | constructor(solutionsCollectorService: SolutionsCollectorService) {
19 | super(solutionsCollectorService, 2021, 2, 'Dive!');
20 | }
21 | private parseCommands(input: string): [string, number][] {
22 | var commands = splitIntoLines(input);
23 | return commands.map((command) => {
24 | var parts = command.split(' ');
25 | return [parts[0], Number(parts[1])];
26 | });
27 | }
28 | override solvePart1(input: string): PuzzleResult {
29 | var commands = this.parseCommands(input);
30 | var depth = 0;
31 | var position = 0;
32 | var depths = [depth];
33 | var positions = [position];
34 | commands.forEach((command) => {
35 | switch (command[0]) {
36 | case 'forward':
37 | position += command[1];
38 | break;
39 | case 'up':
40 | depth -= command[1];
41 | break;
42 | case 'down':
43 | depth += command[1];
44 | break;
45 | }
46 | depths.push(depth);
47 | positions.push(position);
48 | });
49 | return {
50 | result: depth * position,
51 | component: PlotlyGraphComponent,
52 | componentData: {
53 | graphData: [
54 | {
55 | x: positions,
56 | y: depths,
57 | mode: 'lines',
58 | name: 'Measurements',
59 | line: {
60 | color: 'rgba(#ffffff, 0.8)',
61 | },
62 | },
63 | ],
64 | graphLayout: {
65 | yaxis: { title: 'Depth', autorange: 'reversed' },
66 | xaxis: { title: 'Position' },
67 | },
68 | },
69 | };
70 | }
71 | override solvePart2(input: string): PuzzleResult {
72 | var commands = this.parseCommands(input);
73 | var depth = 0;
74 | var position = 0;
75 | var aim = 0;
76 | var depths = [depth];
77 | var positions = [position];
78 | commands.forEach((command) => {
79 | switch (command[0]) {
80 | case 'forward':
81 | position += command[1];
82 | depth += command[1] * aim;
83 | break;
84 | case 'up':
85 | aim -= command[1];
86 | break;
87 | case 'down':
88 | aim += command[1];
89 | break;
90 | }
91 | depths.push(depth);
92 | positions.push(position);
93 | });
94 | return {
95 | result: depth * position,
96 | component: PlotlyGraphComponent,
97 | componentData: {
98 | graphData: [
99 | {
100 | x: positions,
101 | y: depths,
102 | mode: 'lines',
103 | name: 'Measurements',
104 | line: {
105 | color: 'rgba(#ffffff, 0.8)',
106 | },
107 | },
108 | ],
109 | graphLayout: {
110 | yaxis: { title: 'Depth', autorange: 'reversed' },
111 | xaxis: { title: 'Position' },
112 | },
113 | },
114 | };
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/app/solutions2021/day20.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { BaseSolutionService } from '../helper/services/base-solution.service';
3 | import {
4 | ISolutionService,
5 | PuzzleResult,
6 | } from '../helper/services/isolution.service';
7 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
8 | import { splitIntoLines } from '../helper/util-functions/split-into-lines';
9 | import { OceanTrenchVisualizerComponent } from './components/ocean-trench-visualizer/ocean-trench-visualizer.component';
10 |
11 | @Injectable({
12 | providedIn: 'root',
13 | })
14 | export class Day20Service
15 | extends BaseSolutionService
16 | implements ISolutionService
17 | {
18 | constructor(solutionsCollectorService: SolutionsCollectorService) {
19 | super(solutionsCollectorService, 2021, 20, 'Trench Map');
20 | }
21 |
22 | private enhance(
23 | algorithm: number[],
24 | startImage: number[][],
25 | steps: number = 2
26 | ): number[][][] {
27 | var result: number[][][] = [startImage];
28 | var padding = 2;
29 | for (let s = 0; s < steps; s++) {
30 | var enhancedImage: number[][] = [];
31 | var lastImage = result.slice(-1)[0];
32 | var height = lastImage.length;
33 | var width = lastImage[0].length;
34 | for (let y = -padding; y < height + padding - 2; y++) {
35 | var currentRow: number[] = [];
36 | for (let x = -padding; x < width + padding - 2; x++) {
37 | var numbersString = '';
38 | [0, 1, 2].forEach((yIdx) => {
39 | [0, 1, 2].forEach((xIdx) => {
40 | var yPos = y + yIdx;
41 | var xPos = x + xIdx;
42 | if (yPos >= 0 && yPos < height && xPos >= 0 && xPos < width) {
43 | numbersString += lastImage[yPos][xPos].toString();
44 | } else if (algorithm[0] == 1) {
45 | numbersString += (s % 2).toString();
46 | } else {
47 | numbersString += '0';
48 | }
49 | });
50 | });
51 | var kernelValue = Number.parseInt(numbersString, 2);
52 | currentRow.push(algorithm[kernelValue]);
53 | }
54 | enhancedImage.push(currentRow);
55 | }
56 | result.push(enhancedImage);
57 | }
58 |
59 | return result;
60 | }
61 |
62 | override solvePart1(input: string): PuzzleResult {
63 | var lines = splitIntoLines(input);
64 | var algorithm: number[] = lines[0].split('').map((c) => (c == '#' ? 1 : 0));
65 | var image: number[][] = lines
66 | .slice(2)
67 | .map((l) => l.split('').map((c) => (c == '#' ? 1 : 0)));
68 | var images = this.enhance(algorithm, image, 2);
69 | return {
70 | result: images
71 | .slice(-1)[0]
72 | .flat()
73 | .filter((d) => d == 1).length,
74 | component: OceanTrenchVisualizerComponent,
75 | componentData: {
76 | images: images,
77 | },
78 | };
79 | }
80 | override solvePart2(input: string): PuzzleResult {
81 | var lines = splitIntoLines(input);
82 | var algorithm: number[] = lines[0].split('').map((c) => (c == '#' ? 1 : 0));
83 | var image: number[][] = lines
84 | .slice(2)
85 | .map((l) => l.split('').map((c) => (c == '#' ? 1 : 0)));
86 | var images = this.enhance(algorithm, image, 50);
87 | return {
88 | result: images
89 | .slice(-1)[0]
90 | .flat()
91 | .filter((d) => d == 1).length,
92 | component: OceanTrenchVisualizerComponent,
93 | componentData: {
94 | images: images,
95 | },
96 | };
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/app/solutions2021/day25.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { BaseSolutionService } from '../helper/services/base-solution.service';
3 | import {
4 | ISolutionService,
5 | PuzzleResult,
6 | } from '../helper/services/isolution.service';
7 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
8 | import { Point2D } from '../helper/util-functions/point';
9 | import { splitIntoLines } from '../helper/util-functions/split-into-lines';
10 | import { SeaCucumbersVisualizerComponent } from './components/sea-cucumbers-visualizer/sea-cucumbers-visualizer.component';
11 |
12 | @Injectable({
13 | providedIn: 'root',
14 | })
15 | export class Day25Service
16 | extends BaseSolutionService
17 | implements ISolutionService
18 | {
19 | constructor(solutionsCollectorService: SolutionsCollectorService) {
20 | super(solutionsCollectorService, 2021, 25, 'Sea Cucumber');
21 | }
22 |
23 | private parseArea(input: string): string[][] {
24 | return splitIntoLines(input).map((l) => l.split(''));
25 | }
26 |
27 | private moveCucumbers(area: string[][]): string[][][] {
28 | var result: string[][][] = [JSON.parse(JSON.stringify(area))];
29 | var moved = true;
30 | var height = area.length;
31 | var width = area[0].length;
32 | while (moved) {
33 | moved = false;
34 | var horizontalCucumbersToMove: Point2D[] = [];
35 | for (let y = 0; y < height; y++) {
36 | for (let x = 0; x < width; x++) {
37 | if (area[y][x] == '>' && area[y][(x + 1) % width] == '.') {
38 | horizontalCucumbersToMove.push({ x, y });
39 | moved = true;
40 | }
41 | }
42 | }
43 | horizontalCucumbersToMove.forEach(({ x, y }) => {
44 | area[y][x] = '.';
45 | area[y][(x + 1) % width] = '>';
46 | });
47 |
48 | var verticalCucumbersToMove: Point2D[] = [];
49 | for (let y = 0; y < height; y++) {
50 | for (let x = 0; x < width; x++) {
51 | if (area[y][x] == 'v' && area[(y + 1) % height][x] == '.') {
52 | verticalCucumbersToMove.push({ x, y });
53 | moved = true;
54 | }
55 | }
56 | }
57 | verticalCucumbersToMove.forEach(({ x, y }) => {
58 | area[y][x] = '.';
59 | area[(y + 1) % height][x] = 'v';
60 | });
61 | result.push(JSON.parse(JSON.stringify(area)));
62 | }
63 | return result;
64 | }
65 |
66 | override solvePart1(input: string): PuzzleResult {
67 | var startArea = this.parseArea(input);
68 | var result = this.moveCucumbers(startArea);
69 | return {
70 | result: result.length - 1,
71 | component: SeaCucumbersVisualizerComponent,
72 | componentData: {
73 | areas: result,
74 | },
75 | };
76 | }
77 | override solvePart2(input: string): number {
78 | return 0;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/app/solutions2021/day6.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { parseFirstLineIntoNumbers } from '../helper/util-functions/parse-first-line-into-numbers';
10 |
11 | @Injectable({
12 | providedIn: 'root',
13 | })
14 | export class Day6Service
15 | extends BaseSolutionService
16 | implements ISolutionService
17 | {
18 | constructor(solutionsCollectorService: SolutionsCollectorService) {
19 | super(solutionsCollectorService, 2021, 6, 'Lanternfish');
20 | }
21 | private getInitialState(input: string): { [day: number]: number } {
22 | var result: { [day: number]: number } = {};
23 | parseFirstLineIntoNumbers(input).forEach((n) => {
24 | if (!(n in result)) {
25 | result[n] = 0;
26 | }
27 | result[n]++;
28 | });
29 | return result;
30 | }
31 | private solve(input: string, days: number): PuzzleResult {
32 | var currentState = this.getInitialState(input);
33 | var y = [
34 | Object.values(currentState)
35 | .map(Number)
36 | .reduce((a, b) => a + b),
37 | ];
38 | var x = [0];
39 | for (let d = 0; d < days; d++) {
40 | var newState: { [day: number]: number } = {};
41 | Object.keys(currentState)
42 | .map(Number)
43 | .sort()
44 | .forEach((day) => {
45 | if (day > 0) {
46 | if (!(day - 1 in newState)) {
47 | newState[day - 1] = 0;
48 | }
49 | newState[day - 1] += currentState[day];
50 | } else {
51 | newState[6] = currentState[day];
52 | newState[8] = currentState[day];
53 | }
54 | });
55 | currentState = newState;
56 | y.push(
57 | Object.values(currentState)
58 | .map(Number)
59 | .reduce((a, b) => a + b)
60 | );
61 | x.push(d + 1);
62 | }
63 | return {
64 | result: y[y.length - 1],
65 | component: PlotlyGraphComponent,
66 | componentData: {
67 | graphData: [
68 | {
69 | x: x,
70 | y: y,
71 | mode: 'lines',
72 | name: 'Measurements',
73 | line: {
74 | color: '#fad02c',
75 | },
76 | },
77 | ],
78 | graphLayout: {
79 | yaxis: { title: 'Fishes' },
80 | xaxis: { title: 'Days' },
81 | },
82 | },
83 | };
84 | }
85 | override solvePart1(input: string): PuzzleResult {
86 | return this.solve(input, 80);
87 | }
88 | override solvePart2(input: string): PuzzleResult {
89 | return this.solve(input, 256);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/app/solutions2021/day7.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { parseFirstLineIntoNumbers } from '../helper/util-functions/parse-first-line-into-numbers';
10 |
11 | function sumNumber(num: number) {
12 | var rval = 1;
13 | for (var i = 2; i <= num; i++) rval = rval + i;
14 | return rval;
15 | }
16 |
17 | @Injectable({
18 | providedIn: 'root',
19 | })
20 | export class Day7Service
21 | extends BaseSolutionService
22 | implements ISolutionService
23 | {
24 | constructor(solutionsCollectorService: SolutionsCollectorService) {
25 | super(solutionsCollectorService, 2021, 7, 'The Treachery of Whales');
26 | }
27 | override solvePart1(input: string): PuzzleResult {
28 | var positions = parseFirstLineIntoNumbers(input);
29 | var bestPos = -1;
30 | var bestCost = -1;
31 | for (let i = Math.min(...positions); i <= Math.max(...positions); i++) {
32 | var cost = positions
33 | .map((pos) => Math.abs(pos - i))
34 | .reduce((a, b) => a + b);
35 | if (bestPos < 0 || cost < bestCost) {
36 | bestPos = i;
37 | bestCost = cost;
38 | }
39 | }
40 | return {
41 | result: bestCost,
42 | component: PlotlyGraphComponent,
43 | componentData: {
44 | graphData: positions.map((pos, idx) => {
45 | return {
46 | x: [pos, bestPos],
47 | y: [idx, idx],
48 | mode: 'markers',
49 | type: 'scattergl',
50 | showlegend: false,
51 | legendgroup: 'crab',
52 | };
53 | }),
54 | graphLayout: {
55 | yaxis: { title: 'Crabs', visible: false },
56 | xaxis: { title: 'Positions' },
57 | },
58 | },
59 | };
60 | }
61 | override solvePart2(input: string): PuzzleResult {
62 | var positions = parseFirstLineIntoNumbers(input);
63 | var bestPos = -1;
64 | var bestCost = -1;
65 | for (let i = Math.min(...positions); i <= Math.max(...positions); i++) {
66 | var cost = positions
67 | .map((pos) => sumNumber(Math.abs(pos - i)))
68 | .reduce((a, b) => a + b);
69 | if (bestPos < 0 || cost < bestCost) {
70 | bestPos = i;
71 | bestCost = cost;
72 | }
73 | }
74 | return {
75 | result: bestCost,
76 | component: PlotlyGraphComponent,
77 | componentData: {
78 | graphData: positions.map((pos, idx) => {
79 | return {
80 | x: [pos, bestPos],
81 | y: [idx, idx],
82 | mode: 'markers',
83 | type: 'scattergl',
84 | showlegend: false,
85 | legendgroup: 'crab',
86 | };
87 | }),
88 | graphLayout: {
89 | yaxis: { title: 'Crabs', visible: false },
90 | xaxis: { title: 'Positions' },
91 | },
92 | },
93 | };
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/blizzard-visualizer/blizzard-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
![]()
8 |
![]()
9 |
10 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/blizzard-visualizer/blizzard-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 | .grid-wrapper {
6 | display: flex;
7 | justify-content: center;
8 | align-items: center;
9 |
10 | img {
11 | position: absolute;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/blizzard-visualizer/blizzard-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { Point2D } from 'src/app/helper/util-functions/point';
4 | import { Blizzard, getCurrentBlizzardsPositions } from '../../day24.service';
5 |
6 | @Component({
7 | selector: 'aoc-blizzard-visualizer',
8 | templateUrl: './blizzard-visualizer.component.html',
9 | styleUrls: ['./blizzard-visualizer.component.scss'],
10 | })
11 | export class BlizzardVisualizerComponent
12 | extends BaseResultComponent
13 | implements OnInit, AfterViewInit
14 | {
15 | blizzards!: Blizzard[];
16 | moves!: Point2D[];
17 | walls!: Point2D[];
18 | minX!: number;
19 | maxX!: number;
20 | minY!: number;
21 | maxY!: number;
22 | currentIdx: number = 0;
23 | visualizing: boolean = false;
24 | squareWidth: number = 5;
25 | blizzardsCache = {};
26 |
27 | constructor(private el: ElementRef) {
28 | super();
29 | }
30 |
31 | get imageHeight(): number {
32 | return this.maxY - this.minY + 1;
33 | }
34 |
35 | get imageWidth(): number {
36 | return this.maxX - this.minX + 1;
37 | }
38 |
39 | get wallsCanvas(): string {
40 | var canvas = document.createElement('canvas');
41 | let ctx = canvas.getContext('2d');
42 | const magnifier = this.squareWidth;
43 | canvas.width = magnifier * this.imageWidth;
44 | canvas.height = magnifier * this.imageHeight;
45 | ctx!.fillStyle = '#ccc';
46 | this.walls.forEach((wall) => {
47 | ctx!.fillRect(
48 | (wall.x - this.minX) * magnifier,
49 | (wall.y - this.minY) * magnifier,
50 | magnifier,
51 | magnifier
52 | );
53 | });
54 | const data = canvas.toDataURL();
55 | return data;
56 | }
57 |
58 | get imageCanvas(): string {
59 | var canvas = document.createElement('canvas');
60 | let ctx = canvas.getContext('2d');
61 | const magnifier = this.squareWidth;
62 | canvas.width = magnifier * this.imageWidth;
63 | canvas.height = magnifier * this.imageHeight;
64 |
65 | ctx!.fillStyle = 'rgb(250, 208, 44)';
66 | ctx!.fillRect(
67 | (this.moves[this.currentIdx].x - this.minX) * magnifier,
68 | (this.moves[this.currentIdx].y - this.minY) * magnifier,
69 | magnifier,
70 | magnifier
71 | );
72 | ctx!.fillStyle = 'rgba(115,155,208,0.25)';
73 | var currentBlizzard = getCurrentBlizzardsPositions(
74 | this.blizzards,
75 | this.currentIdx,
76 | this.maxX - 1,
77 | this.maxY - 1,
78 | this.blizzardsCache
79 | );
80 | currentBlizzard.forEach((blizzard) => {
81 | ctx!.fillRect(
82 | (blizzard.x - this.minX) * magnifier,
83 | (blizzard.y - this.minY) * magnifier,
84 | magnifier,
85 | magnifier
86 | );
87 | });
88 | const data = canvas.toDataURL();
89 | return data;
90 | }
91 |
92 | ngOnInit(): void {
93 | this.blizzards = this.data.blizzards as Blizzard[];
94 | this.walls = this.data.walls as Point2D[];
95 | this.moves = this.data.moves as Point2D[];
96 | this.currentIdx = 0;
97 | this.minX = Math.min(...this.walls.map((p) => p.x));
98 | this.maxX = Math.max(...this.walls.map((p) => p.x));
99 | this.minY = Math.min(...this.walls.map((p) => p.y));
100 | this.maxY = Math.max(...this.walls.map((p) => p.y));
101 | }
102 |
103 | ngAfterViewInit(): void {
104 | this.blizzardsCache = {};
105 | this.squareWidth = this.el.nativeElement.offsetHeight / this.imageHeight;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/camp-sections-visualizer/camp-sections-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
![]()
15 |
16 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/camp-sections-visualizer/camp-sections-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
6 | .flex-row {
7 | display: flex;
8 | flex-flow: row wrap;
9 |
10 | &>div {
11 | margin-right: 8px;
12 | }
13 | }
14 |
15 | .block {
16 | width: 32px;
17 | height: 32px;
18 | }
19 |
20 | .block-1 {
21 | background-color: #fad02c;
22 | opacity: 0.6;
23 | }
24 |
25 | .block-2 {
26 | background-color: #fff;
27 | opacity: 0.6;
28 | }
29 |
30 | .block-3 {
31 | background-color: #fad02c;
32 | opacity: 1.0;
33 | }
34 |
35 | .grid-wrapper {
36 | display: flex;
37 | justify-content: center;
38 | align-items: center;
39 | }
40 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/camp-sections-visualizer/camp-sections-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
2 | import { min } from 'rxjs';
3 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
4 |
5 | @Component({
6 | selector: 'aoc-camp-sections-visualizer',
7 | templateUrl: './camp-sections-visualizer.component.html',
8 | styleUrls: ['./camp-sections-visualizer.component.scss'],
9 | })
10 | export class CampSectionsVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit, AfterViewInit
13 | {
14 | sections: [number[], number[]][] = [];
15 | squareWidth: number = 5;
16 | minSection: number = 0;
17 | maxSection: number = 0;
18 |
19 | constructor(private el: ElementRef) {
20 | super();
21 | }
22 |
23 | get imageWidth(): number {
24 | return this.maxSection - this.minSection + 1;
25 | }
26 |
27 | get imageCanvas(): string {
28 | var sections = this.sections;
29 |
30 | var canvas = document.createElement('canvas');
31 | let ctx = canvas.getContext('2d');
32 | const magnifier = this.squareWidth;
33 | canvas.width = magnifier * this.imageWidth;
34 | canvas.height = magnifier * this.sections.length;
35 | sections.forEach((ranges, y) => {
36 | Array.range(this.minSection, this.maxSection + 1).forEach(
37 | (sectionId, x) => {
38 | var fillStyle = null;
39 | if (ranges.every((range) => range.includes(sectionId))) {
40 | fillStyle = '#fad02c';
41 | ctx!.globalAlpha = 1.0;
42 | } else if (ranges[0].includes(sectionId)) {
43 | fillStyle = '#fad02c';
44 | ctx!.globalAlpha = 0.6;
45 | } else if (ranges[1].includes(sectionId)) {
46 | fillStyle = '#ffffff';
47 | ctx!.globalAlpha = 0.6;
48 | }
49 |
50 | if (fillStyle != null) {
51 | ctx!.fillStyle = fillStyle;
52 | ctx!.fillRect(x * magnifier, y * magnifier, magnifier, magnifier);
53 | }
54 | }
55 | );
56 | });
57 | const data = canvas.toDataURL();
58 | return data;
59 | }
60 |
61 | ngOnInit(): void {
62 | this.sections = this.data.sections as [number[], number[]][];
63 | var allNumbers: number[] = [];
64 | this.sections.forEach((ranges) => {
65 | allNumbers = allNumbers.concat(ranges.flat());
66 | });
67 | this.minSection = Math.min(...allNumbers);
68 | this.maxSection = Math.max(...allNumbers);
69 | }
70 |
71 | ngAfterViewInit(): void {
72 | this.squareWidth =
73 | this.el.nativeElement.offsetWidth / (2 * this.imageWidth);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/cargo-visualizer/cargo-step-visualizer/cargo-step-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
8 | [{{ element.value }}]
9 |
10 |
11 |
12 |
20 | {{ column + 1 }}
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/cargo-visualizer/cargo-step-visualizer/cargo-step-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: fit-content;
4 | }
5 |
6 | .grid {
7 | margin: 0.75em;
8 | display: grid;
9 | width: fit-content;
10 | column-gap: 8px;
11 | }
12 |
13 | .cargo-cell {
14 | justify-self: center;
15 | min-width: 3ch;
16 | text-align: center;
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/cargo-visualizer/cargo-step-visualizer/cargo-step-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 | import { Stack } from '../../../../helper/util-functions/stack';
3 |
4 | interface CargoElement {
5 | value: string;
6 | row: number;
7 | col: number;
8 | }
9 |
10 | @Component({
11 | selector: 'aoc-cargo-step-visualizer',
12 | templateUrl: './cargo-step-visualizer.component.html',
13 | styleUrls: ['./cargo-step-visualizer.component.scss'],
14 | })
15 | export class CargoStepVisualizerComponent {
16 | @Input() stacks: Stack[] = [];
17 | @Input() showColumns: boolean = true;
18 | @Input() glowColumn?: number;
19 |
20 | get cargoElements(): CargoElement[] {
21 | return this.stacks.flatMap((stack, col) =>
22 | stack.store.map((element, row) => {
23 | return { value: element, row, col };
24 | })
25 | );
26 | }
27 |
28 | get columns(): number[] {
29 | return this.stacks.map((s, idx) => idx);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/cargo-visualizer/cargo-visualizer.component.html:
--------------------------------------------------------------------------------
1 | 0" class="accent-color">
2 |
3 |
12 |
21 |
35 |
49 |
50 |
51 | Animation speed: {{ interval }}ms
52 |
53 |
60 |
61 |
62 |
63 |
64 |
65 | move {{ move.amount }} from
66 | {{ move.from }} to
67 | {{ move.to }}
69 | Iterations: {{ iterations }} / {{ totalIterations }} ({{
70 | (100 * iterations) / totalIterations | number : "1.0-2"
71 | }}%)
72 |
73 |
74 |
75 |
76 |
80 |
81 |
82 |
83 |
86 |
87 |
88 |
89 |
93 |
94 |
95 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/cargo-visualizer/cargo-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
6 | .flex-box {
7 | margin: 0.75em;
8 | display: flex;
9 | flex-direction: column;
10 | width: fit-content;
11 |
12 | .cargo {
13 | justify-content: center;
14 | display: flex;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/cargo-visualizer/cargo-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { CargoMove, CargoSnapshot, CargoStep } from '../../day5.service';
4 |
5 | @Component({
6 | selector: 'aoc-cargo-visualizer',
7 | templateUrl: './cargo-visualizer.component.html',
8 | styleUrls: ['./cargo-visualizer.component.scss'],
9 | })
10 | export class CargoVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit
13 | {
14 | snapshots: CargoSnapshot[] = [];
15 |
16 | currentSnapshotIdx: number = 0;
17 | currentStepIdx: number = 0;
18 | currentStepStateIdx: number = 0;
19 | visualizing: boolean = false;
20 | iterations: number = 0;
21 | totalIterations: number = 0;
22 | interval = 100;
23 |
24 | get snapshot(): CargoSnapshot {
25 | return this.snapshots[this.currentSnapshotIdx];
26 | }
27 |
28 | get move(): CargoMove {
29 | return this.snapshot.move;
30 | }
31 |
32 | get step(): CargoStep {
33 | return this.snapshot.steps[this.currentStepIdx];
34 | }
35 |
36 | ngOnInit(): void {
37 | this.snapshots = this.data.snapshots as CargoSnapshot[];
38 | this.totalIterations =
39 | this.snapshots.flatMap((s) => s.steps.map((x) => 3)).sum() - 1;
40 | }
41 |
42 | pauseVisualization() {
43 | this.visualizing = false;
44 | }
45 |
46 | startVisualization() {
47 | this.visualizing = true;
48 | if (
49 | this.currentStepIdx == this.snapshot.steps.length - 1 &&
50 | this.currentSnapshotIdx == this.snapshots.length - 1 &&
51 | this.currentStepStateIdx == 2
52 | ) {
53 | this.currentStepIdx = 0;
54 | this.currentSnapshotIdx = 0;
55 | this.currentStepStateIdx = 0;
56 | this.iterations = 0;
57 | }
58 | this.loop();
59 | }
60 |
61 | nextStep() {
62 | this.iterations++;
63 | var isLastStepState = this.currentStepStateIdx == 2;
64 | var isLastStep = this.currentStepIdx == this.snapshot.steps.length - 1;
65 |
66 | this.currentStepStateIdx++;
67 |
68 | if (isLastStepState) {
69 | this.currentStepStateIdx = 0;
70 | this.currentStepIdx++;
71 | }
72 |
73 | if (isLastStep && isLastStepState) {
74 | this.currentStepIdx = 0;
75 | this.currentSnapshotIdx++;
76 | }
77 | }
78 |
79 | prevStep() {
80 | this.iterations--;
81 | var isFirstStepState = this.currentStepStateIdx == 0;
82 | var isFirstStep = this.currentStepIdx == 0;
83 |
84 | this.currentStepStateIdx--;
85 |
86 | if (isFirstStepState) {
87 | this.currentStepIdx--;
88 | this.currentStepStateIdx = 2;
89 | }
90 |
91 | if (isFirstStep && isFirstStepState) {
92 | this.currentSnapshotIdx--;
93 | this.currentStepIdx = this.snapshot.steps.length - 1;
94 | }
95 | }
96 |
97 | private loop() {
98 | if (this.visualizing) {
99 | setTimeout(() => {
100 | this.nextStep();
101 | if (
102 | this.currentStepStateIdx < 2 ||
103 | this.currentStepIdx < this.snapshot.steps.length - 1 ||
104 | this.currentSnapshotIdx < this.snapshots.length - 1
105 | ) {
106 | this.loop();
107 | } else {
108 | this.visualizing = false;
109 | }
110 | }, this.interval);
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/datastream-buffer-visualizer/datastream-buffer-visualizer.component.html:
--------------------------------------------------------------------------------
1 | {{ char }}
7 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/datastream-buffer-visualizer/datastream-buffer-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | word-break: break-all;
5 |
6 | .packet-character {
7 | padding: 0 4px;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/datastream-buffer-visualizer/datastream-buffer-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-datastream-buffer-visualizer',
6 | templateUrl: './datastream-buffer-visualizer.component.html',
7 | styleUrls: ['./datastream-buffer-visualizer.component.scss'],
8 | })
9 | export class DatastreamBufferVisualizerComponent
10 | extends BaseResultComponent
11 | implements OnInit
12 | {
13 | message: string[] = [];
14 | index: number = 0;
15 | packetLength: number = 0;
16 | ngOnInit(): void {
17 | this.message = (this.data.message as string).split('');
18 | this.index = this.data.index as number;
19 | this.packetLength = this.data.packetLength as number;
20 | }
21 |
22 | isInPacket(idx: number): boolean {
23 | return idx > this.index - this.packetLength && idx <= this.index;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/device-file-visualizer/device-file-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0" class="monospace">
4 | {{
5 | separator == 0 ? "⠀⠀" : "│⠀"
6 | }}
7 | ├
8 | └
9 |
10 |
11 | 0">⠀
12 | {{ file.fileName }}
17 | ({{ file.isDirectory ? "dir, " : "file, " }}size={{ file.fileSize }})
23 |
24 |
25 |
26 |
27 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/device-file-visualizer/device-file-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | width: 100%;
3 | display: block;
4 | margin-top: -0.4em;
5 |
6 | span {
7 | display: inline-block;
8 | line-height: 1em;
9 | }
10 |
11 | .file-row {
12 | margin-right: 0.5em;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/device-file-visualizer/device-file-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from '../../../helper/components/base-result.component';
3 | import { DeviceFile } from '../../day7.service';
4 |
5 | @Component({
6 | selector: 'aoc-device-file-visualizer',
7 | templateUrl: './device-file-visualizer.component.html',
8 | styleUrls: ['./device-file-visualizer.component.scss'],
9 | })
10 | export class DeviceFileVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit
13 | {
14 | @Input() file!: DeviceFile;
15 | @Input() selectedDirectories!: DeviceFile[];
16 | @Input() depth: number = 0;
17 | @Input() separators: number[] = [];
18 | @Input() isChild: boolean = false;
19 | @Input() isLast: boolean = true;
20 |
21 | ngOnInit(): void {
22 | if (this.data) {
23 | this.file = this.data.file as DeviceFile;
24 | this.selectedDirectories = this.data.selectedDirectories as DeviceFile[];
25 | }
26 | }
27 |
28 | matchDeviceFile(file: DeviceFile): boolean {
29 | return this.selectedDirectories.some((dir) => {
30 | return (
31 | file.isDirectory &&
32 | file.fileName === dir.fileName &&
33 | file.fileSize === dir.fileSize
34 | );
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/elves-moves-visualizer/elves-moves-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
![]()
8 |
9 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/elves-moves-visualizer/elves-moves-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 | .grid-wrapper {
6 | display: flex;
7 | justify-content: center;
8 | align-items: center;
9 | }
10 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/elves-moves-visualizer/elves-moves-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
2 | import { colorInterpolate } from 'src/app/helper/util-functions/color-interpolate';
3 | import { normalize } from 'src/app/helper/util-functions/normalize';
4 | import { BaseResultComponent } from '../../../helper/components/base-result.component';
5 | import { MovingElf } from '../../day23.service';
6 |
7 | @Component({
8 | selector: 'aoc-elves-moves-visualizer',
9 | templateUrl: './elves-moves-visualizer.component.html',
10 | styleUrls: ['./elves-moves-visualizer.component.scss'],
11 | })
12 | export class ElvesMovesVisualizerComponent
13 | extends BaseResultComponent
14 | implements OnInit, AfterViewInit
15 | {
16 | elves!: MovingElf[];
17 | minX!: number;
18 | maxX!: number;
19 | minY!: number;
20 | maxY!: number;
21 | currentIdx: number = 0;
22 | visualizing: boolean = false;
23 | squareWidth: number = 5;
24 |
25 | constructor(private el: ElementRef) {
26 | super();
27 | }
28 |
29 | get imageHeight(): number {
30 | return this.maxY - this.minY + 1;
31 | }
32 |
33 | get imageWidth(): number {
34 | return this.maxX - this.minX + 1;
35 | }
36 |
37 | get imageCanvas(): string {
38 | var canvas = document.createElement('canvas');
39 | let ctx = canvas.getContext('2d');
40 | const magnifier = this.squareWidth;
41 | canvas.width = magnifier * this.imageWidth;
42 | canvas.height = magnifier * this.imageHeight;
43 |
44 | ctx!.fillStyle = 'rgb(250, 208, 44)';
45 | this.elves.forEach((elf) => {
46 | ctx!.fillStyle = colorInterpolate(
47 | 'rgb(250, 208, 44)',
48 | 'rgb(255, 255, 255)',
49 | normalize(
50 | this.currentIdx -
51 | 1 -
52 | elf.moveChanges.findLast((change) => change < this.currentIdx)!,
53 | 0,
54 | 10,
55 | 0,
56 | 1
57 | )
58 | );
59 | ctx!.fillRect(
60 | (elf.positionsList[this.currentIdx].x - this.minX) * magnifier,
61 | (elf.positionsList[this.currentIdx].y - this.minY) * magnifier,
62 | magnifier,
63 | magnifier
64 | );
65 | });
66 | const data = canvas.toDataURL();
67 | return data;
68 | }
69 |
70 | ngOnInit(): void {
71 | this.elves = this.data.elves as MovingElf[];
72 | this.currentIdx = 0;
73 | this.minX = Math.min(
74 | ...this.elves.map((elf) => Math.min(...elf.positionsList.map((p) => p.x)))
75 | );
76 | this.maxX = Math.max(
77 | ...this.elves.map((elf) => Math.max(...elf.positionsList.map((p) => p.x)))
78 | );
79 | this.minY = Math.min(
80 | ...this.elves.map((elf) => Math.min(...elf.positionsList.map((p) => p.y)))
81 | );
82 | this.maxY = Math.max(
83 | ...this.elves.map((elf) => Math.max(...elf.positionsList.map((p) => p.y)))
84 | );
85 | }
86 |
87 | ngAfterViewInit(): void {
88 | this.squareWidth =
89 | this.el.nativeElement.offsetWidth / (3 * this.imageWidth);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/falling-rocks-visualizer/falling-rocks-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
5 | Current rock: {{ currentRock + 1 }}
6 |
7 | Current move:
8 | {{
9 | jets[rocksPositions[currentRock][currentMove].jetIdx] === -1 ? "<" : ">"
10 | }}
11 |
12 |
13 |
![]()
14 |
15 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/falling-rocks-visualizer/falling-rocks-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 | .flex-row {
6 | display: flex;
7 | flex-flow: row wrap;
8 | }
9 | .grid-wrapper {
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/falling-sand-visualizer/falling-sand-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
![]()
8 |
![]()
9 |
10 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/falling-sand-visualizer/falling-sand-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 | .flex-row {
6 | display: flex;
7 | flex-flow: row wrap;
8 | }
9 | .grid-wrapper {
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 |
14 | img {
15 | position: absolute;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/falling-sand-visualizer/falling-sand-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
2 | import { Point2D } from 'src/app/helper/util-functions/point';
3 | import { BaseResultComponent } from '../../../helper/components/base-result.component';
4 |
5 | @Component({
6 | selector: 'aoc-falling-sand-visualizer',
7 | templateUrl: './falling-sand-visualizer.component.html',
8 | styleUrls: ['./falling-sand-visualizer.component.scss'],
9 | })
10 | export class FallingSandVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit, AfterViewInit
13 | {
14 | rocks!: Point2D[];
15 | sands!: Point2D[][];
16 | minX!: number;
17 | maxX!: number;
18 | minY!: number;
19 | maxY!: number;
20 | currentIdx: number = 0;
21 | visualizing: boolean = false;
22 | squareWidth: number = 5;
23 |
24 | constructor(private el: ElementRef) {
25 | super();
26 | }
27 |
28 | get sand(): Point2D[] {
29 | return this.sands[this.currentIdx];
30 | }
31 |
32 | get imageHeight(): number {
33 | return this.maxY - this.minY + 1;
34 | }
35 |
36 | get imageWidth(): number {
37 | return this.maxX - this.minX + 1;
38 | }
39 |
40 | get rockCanvas(): string {
41 | var canvas = document.createElement('canvas');
42 | let ctx = canvas.getContext('2d');
43 | const magnifier = this.squareWidth;
44 | canvas.width = magnifier * this.imageWidth;
45 | canvas.height = magnifier * this.imageHeight;
46 | ctx!.fillStyle = '#ffffff';
47 | this.rocks.forEach((rock) => {
48 | ctx!.fillRect(
49 | (rock.x - this.minX) * magnifier,
50 | (rock.y - this.minY) * magnifier,
51 | magnifier,
52 | magnifier
53 | );
54 | });
55 | const data = canvas.toDataURL();
56 | return data;
57 | }
58 |
59 | get imageCanvas(): string {
60 | var canvas = document.createElement('canvas');
61 | let ctx = canvas.getContext('2d');
62 | const magnifier = this.squareWidth;
63 | canvas.width = magnifier * this.imageWidth;
64 | canvas.height = magnifier * this.imageHeight;
65 | ctx!.fillStyle = '#fad02c';
66 | this.sand.forEach((grain) => {
67 | ctx!.fillRect(
68 | (grain.x - this.minX) * magnifier,
69 | (grain.y - this.minY) * magnifier,
70 | magnifier,
71 | magnifier
72 | );
73 | });
74 | const data = canvas.toDataURL();
75 | return data;
76 | }
77 |
78 | ngOnInit(): void {
79 | this.rocks = this.data.rocks as Point2D[];
80 | this.sands = this.data.sands as Point2D[][];
81 | this.currentIdx = 0;
82 | this.minX = Math.min(
83 | ...this.rocks.concat(this.sands[this.sands.length - 1]).map((p) => p.x)
84 | );
85 | this.maxX = Math.max(
86 | ...this.rocks.concat(this.sands[this.sands.length - 1]).map((p) => p.x)
87 | );
88 | this.minY = 0;
89 | this.maxY = Math.max(
90 | ...this.rocks.concat(this.sands[this.sands.length - 1]).map((p) => p.y)
91 | );
92 | }
93 |
94 | ngAfterViewInit(): void {
95 | this.squareWidth =
96 | this.el.nativeElement.offsetWidth / (3 * this.imageWidth);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkey-map-cube-visualizer/monkey-map-cube-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkey-map-cube-visualizer/monkey-map-cube-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
6 | .scene {
7 | height: 800px;
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkey-math-equations-visualizer/monkey-math-equations-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkey-math-equations-visualizer/monkey-math-equations-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
6 | .network {
7 | height: 800px;
8 | }
9 |
10 | .equations-container {
11 | display: flex;
12 | flex-direction: column;
13 |
14 | ::ng-deep {
15 | .eq-smaller-margin {
16 | margin: 0.25em 0;
17 | }
18 | }
19 | .equation {
20 | margin: 1em 0;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkeys-inspections-visualizer/monkey-inspection-visualizer/monkey-inspection-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | 🐒 #{{ monkeyId }}
5 |
6 | Inspections:
7 | {{ monkeyInspection.inspections }}
9 | Items: {{ items }}
11 | Condition: x % {{ monkeyInspection.divisibleBy }} == 0 ?
13 | {{ monkeyInspection.trueMonkeyIndex }} :
14 | {{ monkeyInspection.falseMonkeyIndex }}
16 |
17 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkeys-inspections-visualizer/monkey-inspection-visualizer/monkey-inspection-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: fit-content;
4 | justify-self: center;
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkeys-inspections-visualizer/monkey-inspection-visualizer/monkey-inspection-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 | import { Monkey } from 'src/app/solutions2022/day11.service';
3 |
4 | @Component({
5 | selector: 'aoc-monkey-inspection-visualizer',
6 | templateUrl: './monkey-inspection-visualizer.component.html',
7 | styleUrls: ['./monkey-inspection-visualizer.component.scss'],
8 | })
9 | export class MonkeyInspectionVisualizerComponent {
10 | @Input() monkeyId!: number;
11 | @Input() monkeyInspection!: Monkey;
12 |
13 | get items(): string {
14 | return this.monkeyInspection.items.map((item) => item.value).join(', ');
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkeys-inspections-visualizer/monkeys-inspections-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkeys-inspections-visualizer/monkeys-inspections-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
6 | .grid {
7 | display: grid;
8 | grid-template-columns: repeat(4, 1fr);
9 | column-gap: 0.5em;
10 | row-gap: 0.5em;
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/monkeys-inspections-visualizer/monkeys-inspections-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from '../../../helper/components/base-result.component';
3 | import { Monkey } from '../../day11.service';
4 |
5 | @Component({
6 | selector: 'aoc-monkeys-inspections-visualizer',
7 | templateUrl: './monkeys-inspections-visualizer.component.html',
8 | styleUrls: ['./monkeys-inspections-visualizer.component.scss'],
9 | })
10 | export class MonkeysInspectionsVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit
13 | {
14 | currentIdx: number = 0;
15 | iterations!: number;
16 |
17 | monkeysSnapshots: Monkey[][] = [];
18 |
19 | get monkeys(): Monkey[] {
20 | return this.monkeysSnapshots[this.currentIdx];
21 | }
22 |
23 | ngOnInit(): void {
24 | this.monkeysSnapshots = this.data.monkeysSnapshots as Monkey[][];
25 | this.iterations = this.monkeysSnapshots.length;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/packet-numbers-visualizer/packet-numbers-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | {{ packetNumber | json }}
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/packet-numbers-visualizer/packet-numbers-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/packet-numbers-visualizer/packet-numbers-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { PacketNumber } from '../../day13.service';
4 |
5 | @Component({
6 | selector: 'aoc-packet-numbers-visualizer',
7 | templateUrl: './packet-numbers-visualizer.component.html',
8 | styleUrls: ['./packet-numbers-visualizer.component.scss'],
9 | })
10 | export class PacketNumbersVisualizerComponent
11 | extends BaseResultComponent
12 | implements OnInit
13 | {
14 | packetNumbersGroups!: PacketNumber[][];
15 | highlightIndexes!: number[][];
16 |
17 | isHighlighted(i: number, j: number): boolean {
18 | return this.highlightIndexes.some((pair) => pair[0] === i && pair[1] === j);
19 | }
20 |
21 | ngOnInit(): void {
22 | this.packetNumbersGroups = this.data.packetNumbers as PacketNumber[][];
23 | this.highlightIndexes = this.data.highlightIndexes as number[][];
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/pressure-valves-visualizer/pressure-valves-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/pressure-valves-visualizer/pressure-valves-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | .network {
2 | height: 800px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/rope-bridge-visualizer/rope-bridge-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | Direction {{ move.direction }}
9 | Steps {{ move.distance }}
11 |
12 |
13 |
14 |
19 | H
20 |
21 |
26 |
27 | T
28 |
29 |
30 |
36 |
42 | .
43 |
44 |
45 |
51 | s
52 |
53 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/rope-bridge-visualizer/rope-bridge-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
6 | .grid-wrapper {
7 | display: flex;
8 | justify-content: center;
9 | align-items: center;
10 | }
11 |
12 | .grid {
13 | margin: 0.75em;
14 | display: grid;
15 | width: fit-content;
16 | }
17 |
18 | .rope-cell {
19 | height: 100%;
20 | width: 100%;
21 | display: flex;
22 | & > span {
23 | margin: auto;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/rope-bridge-visualizer/rope-bridge-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from 'src/app/helper/components/base-result.component';
3 | import { Point2D } from 'src/app/helper/util-functions/point';
4 | import { RopeMove } from '../../day9.service';
5 |
6 | @Component({
7 | selector: 'aoc-rope-bridge-visualizer',
8 | templateUrl: './rope-bridge-visualizer.component.html',
9 | styleUrls: ['./rope-bridge-visualizer.component.scss'],
10 | })
11 | export class RopeBridgeVisualizerComponent
12 | extends BaseResultComponent
13 | implements OnInit, AfterViewInit
14 | {
15 | currentIdx: number = 0;
16 |
17 | headMoves!: { move: RopeMove; position: Point2D }[];
18 | knotsMoves!: Point2D[][];
19 | minX!: number;
20 | maxX!: number;
21 | minY!: number;
22 | maxY!: number;
23 |
24 | squareWidth: number = 5;
25 |
26 | get move(): RopeMove {
27 | return this.headMoves[this.currentIdx].move;
28 | }
29 |
30 | get head(): Point2D {
31 | return this.headMoves[this.currentIdx].position;
32 | }
33 |
34 | get tail(): Point2D {
35 | return this.knotsMoves.slice(-1)[0][this.currentIdx];
36 | }
37 |
38 | get tailTrail(): Point2D[] {
39 | return this.knotsMoves.slice(-1)[0].slice(0, this.currentIdx + 1);
40 | }
41 |
42 | get body(): Point2D[] {
43 | return this.knotsMoves
44 | .slice(0, -1)
45 | .map((knotMoves) => knotMoves[this.currentIdx]);
46 | }
47 |
48 | get gridRepeatStyle(): object {
49 | return {
50 | 'grid-template-columns': `repeat(${this.minX + this.maxX + 1}, ${
51 | this.squareWidth
52 | }px)`,
53 | 'grid-template-rows': `repeat(${this.minY + this.maxY + 1}, ${
54 | this.squareWidth
55 | }px)`,
56 | };
57 | }
58 |
59 | constructor(private el: ElementRef) {
60 | super();
61 | }
62 |
63 | ngOnInit(): void {
64 | this.headMoves = this.data.headMoves as {
65 | move: RopeMove;
66 | position: Point2D;
67 | }[];
68 | this.knotsMoves = this.data.knotsMoves as Point2D[][];
69 |
70 | this.minX = -1 * Math.min(...this.headMoves.map((m) => m.position.x));
71 | this.maxX = Math.max(...this.headMoves.map((m) => m.position.x));
72 | this.minY = -1 * Math.min(...this.headMoves.map((m) => m.position.y));
73 | this.maxY = Math.max(...this.headMoves.map((m) => m.position.y));
74 | }
75 |
76 | ngAfterViewInit(): void {
77 | this.squareWidth =
78 | this.el.nativeElement.offsetWidth / ((this.minX + this.maxX + 1) * 2);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/snafu-numbers-visualizer/snafu-numbers-visualizer.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | {{ snafuNumber }} =>
8 | {{ parsedNumbers[i] }}
9 |
10 |
11 |
12 |
13 | {{ finalNumber }} = {{ factoredSnafuNumber }} =
14 | {{ finalSnafuNumber }}
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/snafu-numbers-visualizer/snafu-numbers-visualizer.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | }
5 |
6 | .grid-wrapper {
7 | display: flex;
8 | flex-direction: column;
9 | justify-content: center;
10 | align-items: center;
11 | }
12 |
13 | .grid {
14 | display: grid;
15 | grid-template-columns: repeat(8, 1fr);
16 | column-gap: 0.5em;
17 | row-gap: 0.5em;
18 | }
19 |
20 | .grid-cell {
21 | justify-self: center;
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/solutions2022/components/snafu-numbers-visualizer/snafu-numbers-visualizer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { BaseResultComponent } from '../../../helper/components/base-result.component';
3 |
4 | @Component({
5 | selector: 'aoc-snafu-numbers-visualizer',
6 | templateUrl: './snafu-numbers-visualizer.component.html',
7 | styleUrls: ['./snafu-numbers-visualizer.component.scss'],
8 | })
9 | export class SnafuNumbersVisualizerComponent
10 | extends BaseResultComponent
11 | implements OnInit
12 | {
13 | snafuNumbers!: string[];
14 | parsedNumbers!: number[];
15 | finalNumber!: number;
16 | finalSnafuNumber!: string;
17 |
18 | get factoredSnafuNumber(): string {
19 | return this.finalSnafuNumber
20 | .split('')
21 | .reverse()
22 | .map(
23 | (char, idx) =>
24 | `${char.replace('-', '-1').replace('=', '-2')} * 5^${idx}`
25 | )
26 | .reverse()
27 | .join(' + ');
28 | }
29 |
30 | ngOnInit(): void {
31 | this.snafuNumbers = this.data.snafuNumbers as string[];
32 | this.parsedNumbers = this.data.parsedNumbers as number[];
33 | this.finalNumber = this.data.finalNumber as number;
34 | this.finalSnafuNumber = this.data.finalSnafuNumber as string;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/app/solutions2022/day1.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { parseIntoNumbers } from '../helper/util-functions/parse-into-numbers';
10 | import { sumNumbers } from '../helper/util-functions/sum';
11 |
12 | @Injectable({
13 | providedIn: 'root',
14 | })
15 | export class Day1Service
16 | extends BaseSolutionService
17 | implements ISolutionService
18 | {
19 | constructor(solutionsCollectorService: SolutionsCollectorService) {
20 | super(solutionsCollectorService, 2022, 1, 'Calorie Counting');
21 | }
22 | override solvePart1(input: string): PuzzleResult {
23 | var groups = input.split('\n\n').map(parseIntoNumbers);
24 | var intakes = groups.map(sumNumbers);
25 | var result = Math.max(...intakes);
26 | return {
27 | result: result,
28 | component: PlotlyGraphComponent,
29 | componentData: {
30 | graphData: [
31 | {
32 | x: intakes.map((val, idx) => idx + 1),
33 | y: intakes,
34 | type: 'bar',
35 | marker: { color: '#fad02c' },
36 | },
37 | ],
38 | graphLayout: {
39 | yaxis: { title: 'Calories sum' },
40 | xaxis: { title: 'Elf', automargin: true },
41 | },
42 | },
43 | };
44 | }
45 | override solvePart2(input: string): PuzzleResult {
46 | var groups = input.split('\n\n').map(parseIntoNumbers);
47 | var intakes = groups
48 | .map(sumNumbers)
49 | .map((val, idx) => [val, idx + 1])
50 | .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
51 |
52 | var triple_intakes = intakes.slice(0, -2).map((val, idx) => {
53 | var sub_arr = intakes.slice(idx, idx + 3);
54 | return [
55 | sub_arr.reduce((acc, cur) => {
56 | return acc + cur[0];
57 | }, 0),
58 | sub_arr.map((x) => x[1]).join(' + '),
59 | ];
60 | });
61 |
62 | return {
63 | result: triple_intakes.slice(-1)[0][0],
64 | component: PlotlyGraphComponent,
65 | componentData: {
66 | graphData: [
67 | {
68 | x: triple_intakes.map((val) => val[1]),
69 | y: triple_intakes.map((val) => val[0]),
70 | type: 'bar',
71 | marker: { color: '#fad02c' },
72 | },
73 | ],
74 | graphLayout: {
75 | yaxis: { title: 'Calories sum' },
76 | xaxis: { title: 'Elf', type: 'category', automargin: true },
77 | },
78 | },
79 | };
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/app/solutions2022/day25.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { splitIntoLines } from '../helper/util-functions/split-into-lines';
10 | import { SnafuNumbersVisualizerComponent } from './components/snafu-numbers-visualizer/snafu-numbers-visualizer.component';
11 |
12 | function fromSNAFU(value: string): number {
13 | return value
14 | .split('')
15 | .reverse()
16 | .map((char, idx) => {
17 | var base = Math.pow(5, idx);
18 | switch (char) {
19 | case '=':
20 | return base * -2;
21 | case '-':
22 | return base * -1;
23 | default:
24 | return base * Number(char);
25 | }
26 | })
27 | .sum();
28 | }
29 |
30 | // Inspired by u/ai_prof
31 | // https://www.reddit.com/r/adventofcode/comments/zur1an/comment/j1qmqf1/
32 | function toSNAFU(value: number): string {
33 | if (value == 0) return '';
34 |
35 | var quotient = Math.floor(value / 5);
36 | switch (value % 5) {
37 | case 3:
38 | return toSNAFU(1 + quotient) + '=';
39 | case 4:
40 | return toSNAFU(1 + quotient) + '-';
41 | default:
42 | return toSNAFU(quotient) + (value % 5).toString();
43 | }
44 | }
45 |
46 | @Injectable({
47 | providedIn: 'root',
48 | })
49 | export class Day25Service
50 | extends BaseSolutionService
51 | implements ISolutionService
52 | {
53 | constructor(solutionsCollectorService: SolutionsCollectorService) {
54 | super(solutionsCollectorService, 2022, 25, 'Full of Hot Air');
55 | }
56 | override solvePart1(input: string): PuzzleResult {
57 | var lines = splitIntoLines(input, true);
58 | var numbers = lines.map(fromSNAFU);
59 | var numbersSum = numbers.sum();
60 | var snafuNumber = toSNAFU(numbersSum);
61 | return {
62 | result: snafuNumber,
63 | component: SnafuNumbersVisualizerComponent,
64 | componentData: {
65 | snafuNumbers: lines,
66 | parsedNumbers: numbers,
67 | finalNumber: numbersSum,
68 | finalSnafuNumber: snafuNumber,
69 | },
70 | };
71 | }
72 | override solvePart2(input: string): number {
73 | return 0;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/solutions2022/day4.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { splitIntoLines } from '../helper/util-functions/split-into-lines';
10 | import { CampSectionsVisualizerComponent } from './components/camp-sections-visualizer/camp-sections-visualizer.component';
11 |
12 | export class Sections {
13 | protected elf1Start: number;
14 | protected elf1End: number;
15 | protected elf2Start: number;
16 | protected elf2End: number;
17 |
18 | constructor(inputLine: string) {
19 | var parts = inputLine.split(',');
20 | var elf1Range = parts[0].split('-').map(Number);
21 | var elf2Range = parts[1].split('-').map(Number);
22 |
23 | this.elf1Start = elf1Range[0];
24 | this.elf1End = elf1Range[1];
25 |
26 | this.elf2Start = elf2Range[0];
27 | this.elf2End = elf2Range[1];
28 | }
29 |
30 | get ranges(): [number[], number[]] {
31 | return [
32 | Array.range(this.elf1Start, this.elf1End + 1),
33 | Array.range(this.elf2Start, this.elf2End + 1),
34 | ];
35 | }
36 |
37 | get isTotalOverlap(): boolean {
38 | return (
39 | (this.elf1Start <= this.elf2Start && this.elf1End >= this.elf2End) ||
40 | (this.elf2Start <= this.elf1Start && this.elf2End >= this.elf1End)
41 | );
42 | }
43 |
44 | get overlapLength(): number {
45 | var ranges = this.ranges;
46 | var frequency = ranges[0]
47 | .concat(ranges[1])
48 | .reduce(function (acc: { [item: number]: number }, curr: number) {
49 | return acc[curr] ? ++acc[curr] : (acc[curr] = 1), acc;
50 | }, {});
51 | return Object.entries(frequency).filter(([key, value]) => value > 1).length;
52 | }
53 | }
54 |
55 | @Injectable({
56 | providedIn: 'root',
57 | })
58 | export class Day4Service
59 | extends BaseSolutionService
60 | implements ISolutionService
61 | {
62 | constructor(solutionsCollectorService: SolutionsCollectorService) {
63 | super(solutionsCollectorService, 2022, 4, 'Camp Cleanup');
64 | }
65 | override solvePart1(input: string): PuzzleResult {
66 | var sections = splitIntoLines(input).map((line) => new Sections(line));
67 | return {
68 | result: sections.filter((x) => x.isTotalOverlap).length,
69 | component: CampSectionsVisualizerComponent,
70 | componentData: {
71 | sections: sections.map((section) => section.ranges),
72 | },
73 | };
74 | }
75 | override solvePart2(input: string): PuzzleResult {
76 | var sections = splitIntoLines(input).map((line) => new Sections(line));
77 | var overlaps = sections.map((x) => x.overlapLength);
78 | var overlapsFrequency = overlaps.reduce(function (
79 | acc: { [item: number]: number },
80 | curr: number
81 | ) {
82 | return acc[curr] ? ++acc[curr] : (acc[curr] = 1), acc;
83 | },
84 | {});
85 | return {
86 | result: overlaps.filter((x) => x > 0).length,
87 | component: PlotlyGraphComponent,
88 | componentData: {
89 | graphData: [
90 | {
91 | x: Object.entries(overlapsFrequency).map(([key, value]) => key),
92 | y: Object.entries(overlapsFrequency).map(([key, value]) => value),
93 | type: 'bar',
94 | marker: { color: '#fad02c' },
95 | },
96 | ],
97 | graphLayout: {
98 | yaxis: { title: 'Count' },
99 | xaxis: { title: 'Overlap size', automargin: true },
100 | },
101 | },
102 | };
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/app/solutions2022/day6.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 | import { splitIntoLines } from '../helper/util-functions/split-into-lines';
10 | import { DatastreamBufferVisualizerComponent } from './components/datastream-buffer-visualizer/datastream-buffer-visualizer.component';
11 |
12 | function findStartOfPacket(message: string, markerLength: number): number {
13 | return (
14 | message
15 | .split('')
16 | .findIndex(
17 | (buffer, idx) =>
18 | new Set(message.slice(idx, idx + markerLength)).size === markerLength
19 | ) + markerLength
20 | );
21 | }
22 |
23 | @Injectable({
24 | providedIn: 'root',
25 | })
26 | export class Day6Service
27 | extends BaseSolutionService
28 | implements ISolutionService
29 | {
30 | constructor(solutionsCollectorService: SolutionsCollectorService) {
31 | super(solutionsCollectorService, 2022, 6, 'Tuning Trouble');
32 | }
33 | override solvePart1(input: string): PuzzleResult {
34 | var datastreamBuffer = splitIntoLines(input)[0];
35 | var result = findStartOfPacket(datastreamBuffer, 4);
36 | return {
37 | result: result,
38 | component: DatastreamBufferVisualizerComponent,
39 | componentData: {
40 | index: result,
41 | message: datastreamBuffer,
42 | packetLength: 4,
43 | },
44 | };
45 | }
46 | override solvePart2(input: string): PuzzleResult {
47 | var datastreamBuffer = splitIntoLines(input)[0];
48 | var result = findStartOfPacket(datastreamBuffer, 14);
49 | return {
50 | result: result,
51 | component: DatastreamBufferVisualizerComponent,
52 | componentData: {
53 | index: result,
54 | message: datastreamBuffer,
55 | packetLength: 14,
56 | },
57 | };
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/app/solutions2022/web-workers/day16.worker.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import '../../helper/util-functions/extensions';
3 | import { findBestValveOpeningMoves } from '../helper/day16';
4 |
5 | addEventListener('message', async ({ data }) => {
6 | var idx = data[0];
7 | var move = data[1];
8 | console.log('Worker start', idx);
9 | var bestPotentialMoves = findBestValveOpeningMoves(
10 | data[2],
11 | data[3],
12 | data[4],
13 | data[5],
14 | undefined,
15 | { value: -1, higherValue: idx }
16 | );
17 | postMessage({ move, bestPotentialMoves });
18 | });
19 |
--------------------------------------------------------------------------------
/src/app/solutions2022/web-workers/day19.worker.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import '../../helper/util-functions/extensions';
3 | import { evaluateBlueprint } from '../helper/day19';
4 |
5 | addEventListener('message', async ({ data }) => {
6 | console.log('Worker start', data[0].id);
7 | var { materials, robots } = evaluateBlueprint(data[0], data[1], data[2]);
8 | postMessage({ blueprint: data[0], materials, robots });
9 | });
10 |
--------------------------------------------------------------------------------
/src/app/template/solution-template.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { PlotlyGraphComponent } from '../helper/components/plotly-graph/plotly-graph.component';
3 | import { BaseSolutionService } from '../helper/services/base-solution.service';
4 | import {
5 | ISolutionService,
6 | PuzzleResult,
7 | } from '../helper/services/isolution.service';
8 | import { SolutionsCollectorService } from '../helper/services/solutions-collector.service';
9 |
10 | @Injectable({
11 | providedIn: 'root',
12 | })
13 | export class Day0Service
14 | extends BaseSolutionService
15 | implements ISolutionService
16 | {
17 | constructor(solutionsCollectorService: SolutionsCollectorService) {
18 | super(solutionsCollectorService, 2020, 0, 'template');
19 | }
20 | override solvePart1(
21 | input: string
22 | ):
23 | | string
24 | | number
25 | | PuzzleResult
26 | | Promise
27 | | Promise
28 | | Promise {
29 | return {
30 | result: 0,
31 | component: PlotlyGraphComponent,
32 | componentData: {
33 | graphData: [],
34 | graphLayout: {},
35 | },
36 | };
37 | }
38 | override solvePart2(
39 | input: string
40 | ):
41 | | string
42 | | number
43 | | PuzzleResult
44 | | Promise
45 | | Promise
46 | | Promise {
47 | return {
48 | result: 0,
49 | component: PlotlyGraphComponent,
50 | componentData: {
51 | graphData: [],
52 | graphLayout: {},
53 | },
54 | };
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/src/assets/.gitkeep
--------------------------------------------------------------------------------
/src/assets/inputs/2021/1.txt:
--------------------------------------------------------------------------------
1 | 199
2 | 200
3 | 208
4 | 210
5 | 200
6 | 207
7 | 240
8 | 269
9 | 260
10 | 263
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/10.txt:
--------------------------------------------------------------------------------
1 | [({(<(())[]>[[{[]{<()<>>
2 | [(()[<>])]({[<{<<[]>>(
3 | {([(<{}[<>[]}>{[]{[(<()>
4 | (((({<>}<{<{<>}{[]{[]{}
5 | [[<[([]))<([[{}[[()]]]
6 | [{[{({}]{}}([{[{{{}}([]
7 | {<[[]]>}<{[{[{[]{()[[[]
8 | [<(<(<(<{}))><([]([]()
9 | <{([([[(<>()){}]>(<<{{
10 | <{([{{}}[<[[[<>{}]]]>[]]
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/11.txt:
--------------------------------------------------------------------------------
1 | 5483143223
2 | 2745854711
3 | 5264556173
4 | 6141336146
5 | 6357385478
6 | 4167524645
7 | 2176841721
8 | 6882881134
9 | 4846848554
10 | 5283751526
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/12.txt:
--------------------------------------------------------------------------------
1 | start-A
2 | start-b
3 | A-c
4 | A-b
5 | b-d
6 | A-end
7 | b-end
8 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/13.txt:
--------------------------------------------------------------------------------
1 | 6,10
2 | 0,14
3 | 9,10
4 | 0,3
5 | 10,4
6 | 4,11
7 | 6,0
8 | 6,12
9 | 4,1
10 | 0,13
11 | 10,12
12 | 3,4
13 | 3,0
14 | 8,4
15 | 1,10
16 | 2,14
17 | 8,10
18 | 9,0
19 |
20 | fold along y=7
21 | fold along x=5
22 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/14.txt:
--------------------------------------------------------------------------------
1 | NNCB
2 |
3 | CH -> B
4 | HH -> N
5 | CB -> H
6 | NH -> C
7 | HB -> C
8 | HC -> B
9 | HN -> C
10 | NN -> C
11 | BH -> H
12 | NC -> B
13 | NB -> B
14 | BN -> B
15 | BB -> N
16 | BC -> B
17 | CC -> N
18 | CN -> C
19 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/15.txt:
--------------------------------------------------------------------------------
1 | 1163751742
2 | 1381373672
3 | 2136511328
4 | 3694931569
5 | 7463417111
6 | 1319128137
7 | 1359912421
8 | 3125421639
9 | 1293138521
10 | 2311944581
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/16.txt:
--------------------------------------------------------------------------------
1 | 9C0141080250320F1802104A08
2 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/17.txt:
--------------------------------------------------------------------------------
1 | target area: x=20..30, y=-10..-5
2 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/18.txt:
--------------------------------------------------------------------------------
1 | [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
2 | [[[5,[2,8]],4],[5,[[9,9],0]]]
3 | [6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
4 | [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
5 | [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]]
6 | [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]]
7 | [[[[5,4],[7,7]],8],[[8,3],8]]
8 | [[9,3],[[9,9],[6,[4,9]]]]
9 | [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
10 | [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/19.txt:
--------------------------------------------------------------------------------
1 | --- scanner 0 ---
2 | 404,-588,-901
3 | 528,-643,409
4 | -838,591,734
5 | 390,-675,-793
6 | -537,-823,-458
7 | -485,-357,347
8 | -345,-311,381
9 | -661,-816,-575
10 | -876,649,763
11 | -618,-824,-621
12 | 553,345,-567
13 | 474,580,667
14 | -447,-329,318
15 | -584,868,-557
16 | 544,-627,-890
17 | 564,392,-477
18 | 455,729,728
19 | -892,524,684
20 | -689,845,-530
21 | 423,-701,434
22 | 7,-33,-71
23 | 630,319,-379
24 | 443,580,662
25 | -789,900,-551
26 | 459,-707,401
27 |
28 | --- scanner 1 ---
29 | 686,422,578
30 | 605,423,415
31 | 515,917,-361
32 | -336,658,858
33 | 95,138,22
34 | -476,619,847
35 | -340,-569,-846
36 | 567,-361,727
37 | -460,603,-452
38 | 669,-402,600
39 | 729,430,532
40 | -500,-761,534
41 | -322,571,750
42 | -466,-666,-811
43 | -429,-592,574
44 | -355,545,-477
45 | 703,-491,-529
46 | -328,-685,520
47 | 413,935,-424
48 | -391,539,-444
49 | 586,-435,557
50 | -364,-763,-893
51 | 807,-499,-711
52 | 755,-354,-619
53 | 553,889,-390
54 |
55 | --- scanner 2 ---
56 | 649,640,665
57 | 682,-795,504
58 | -784,533,-524
59 | -644,584,-595
60 | -588,-843,648
61 | -30,6,44
62 | -674,560,763
63 | 500,723,-460
64 | 609,671,-379
65 | -555,-800,653
66 | -675,-892,-343
67 | 697,-426,-610
68 | 578,704,681
69 | 493,664,-388
70 | -671,-858,530
71 | -667,343,800
72 | 571,-461,-707
73 | -138,-166,112
74 | -889,563,-600
75 | 646,-828,498
76 | 640,759,510
77 | -630,509,768
78 | -681,-892,-333
79 | 673,-379,-804
80 | -742,-814,-386
81 | 577,-820,562
82 |
83 | --- scanner 3 ---
84 | -589,542,597
85 | 605,-692,669
86 | -500,565,-823
87 | -660,373,557
88 | -458,-679,-417
89 | -488,449,543
90 | -626,468,-788
91 | 338,-750,-386
92 | 528,-832,-391
93 | 562,-778,733
94 | -938,-730,414
95 | 543,643,-506
96 | -524,371,-870
97 | 407,773,750
98 | -104,29,83
99 | 378,-903,-323
100 | -778,-728,485
101 | 426,699,580
102 | -438,-605,-362
103 | -469,-447,-387
104 | 509,732,623
105 | 647,635,-688
106 | -868,-804,481
107 | 614,-800,639
108 | 595,780,-596
109 |
110 | --- scanner 4 ---
111 | 727,592,562
112 | -293,-554,779
113 | 441,611,-461
114 | -714,465,-776
115 | -743,427,-804
116 | -660,-479,-426
117 | 832,-632,460
118 | 927,-485,-438
119 | 408,393,-506
120 | 466,436,-512
121 | 110,16,151
122 | -258,-428,682
123 | -393,719,612
124 | -211,-452,876
125 | 808,-476,-593
126 | -575,615,604
127 | -485,667,467
128 | -680,325,-822
129 | -627,-443,-432
130 | 872,-547,-609
131 | 833,512,582
132 | 807,604,487
133 | 839,-516,451
134 | 891,-625,532
135 | -652,-548,-490
136 | 30,-46,-14
137 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/2.txt:
--------------------------------------------------------------------------------
1 | forward 5
2 | down 5
3 | forward 8
4 | up 3
5 | down 8
6 | forward 2
7 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/20.txt:
--------------------------------------------------------------------------------
1 | ..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
2 |
3 | #..#.
4 | #....
5 | ##..#
6 | ..#..
7 | ..###
8 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/21.txt:
--------------------------------------------------------------------------------
1 | Player 1 starting position: 4
2 | Player 2 starting position: 8
3 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/22.txt:
--------------------------------------------------------------------------------
1 | on x=-5..47,y=-31..22,z=-19..33
2 | on x=-44..5,y=-27..21,z=-14..35
3 | on x=-49..-1,y=-11..42,z=-10..38
4 | on x=-20..34,y=-40..6,z=-44..1
5 | off x=26..39,y=40..50,z=-2..11
6 | on x=-41..5,y=-41..6,z=-36..8
7 | off x=-43..-33,y=-45..-28,z=7..25
8 | on x=-33..15,y=-32..19,z=-34..11
9 | off x=35..47,y=-46..-34,z=-11..5
10 | on x=-14..36,y=-6..44,z=-16..29
11 | on x=-57795..-6158,y=29564..72030,z=20435..90618
12 | on x=36731..105352,y=-21140..28532,z=16094..90401
13 | on x=30999..107136,y=-53464..15513,z=8553..71215
14 | on x=13528..83982,y=-99403..-27377,z=-24141..23996
15 | on x=-72682..-12347,y=18159..111354,z=7391..80950
16 | on x=-1060..80757,y=-65301..-20884,z=-103788..-16709
17 | on x=-83015..-9461,y=-72160..-8347,z=-81239..-26856
18 | on x=-52752..22273,y=-49450..9096,z=54442..119054
19 | on x=-29982..40483,y=-108474..-28371,z=-24328..38471
20 | on x=-4958..62750,y=40422..118853,z=-7672..65583
21 | on x=55694..108686,y=-43367..46958,z=-26781..48729
22 | on x=-98497..-18186,y=-63569..3412,z=1232..88485
23 | on x=-726..56291,y=-62629..13224,z=18033..85226
24 | on x=-110886..-34664,y=-81338..-8658,z=8914..63723
25 | on x=-55829..24974,y=-16897..54165,z=-121762..-28058
26 | on x=-65152..-11147,y=22489..91432,z=-58782..1780
27 | on x=-120100..-32970,y=-46592..27473,z=-11695..61039
28 | on x=-18631..37533,y=-124565..-50804,z=-35667..28308
29 | on x=-57817..18248,y=49321..117703,z=5745..55881
30 | on x=14781..98692,y=-1341..70827,z=15753..70151
31 | on x=-34419..55919,y=-19626..40991,z=39015..114138
32 | on x=-60785..11593,y=-56135..2999,z=-95368..-26915
33 | on x=-32178..58085,y=17647..101866,z=-91405..-8878
34 | on x=-53655..12091,y=50097..105568,z=-75335..-4862
35 | on x=-111166..-40997,y=-71714..2688,z=5609..50954
36 | on x=-16602..70118,y=-98693..-44401,z=5197..76897
37 | on x=16383..101554,y=4615..83635,z=-44907..18747
38 | off x=-95822..-15171,y=-19987..48940,z=10804..104439
39 | on x=-89813..-14614,y=16069..88491,z=-3297..45228
40 | on x=41075..99376,y=-20427..49978,z=-52012..13762
41 | on x=-21330..50085,y=-17944..62733,z=-112280..-30197
42 | on x=-16478..35915,y=36008..118594,z=-7885..47086
43 | off x=-98156..-27851,y=-49952..43171,z=-99005..-8456
44 | off x=2032..69770,y=-71013..4824,z=7471..94418
45 | on x=43670..120875,y=-42068..12382,z=-24787..38892
46 | off x=37514..111226,y=-45862..25743,z=-16714..54663
47 | off x=25699..97951,y=-30668..59918,z=-15349..69697
48 | off x=-44271..17935,y=-9516..60759,z=49131..112598
49 | on x=-61695..-5813,y=40978..94975,z=8655..80240
50 | off x=-101086..-9439,y=-7088..67543,z=33935..83858
51 | off x=18020..114017,y=-48931..32606,z=21474..89843
52 | off x=-77139..10506,y=-89994..-18797,z=-80..59318
53 | off x=8476..79288,y=-75520..11602,z=-96624..-24783
54 | on x=-47488..-1262,y=24338..100707,z=16292..72967
55 | off x=-84341..13987,y=2429..92914,z=-90671..-1318
56 | off x=-37810..49457,y=-71013..-7894,z=-105357..-13188
57 | off x=-27365..46395,y=31009..98017,z=15428..76570
58 | off x=-70369..-16548,y=22648..78696,z=-1892..86821
59 | on x=-53470..21291,y=-120233..-33476,z=-44150..38147
60 | off x=-93533..-4276,y=-16170..68771,z=-104985..-24507
61 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/23.txt:
--------------------------------------------------------------------------------
1 | #############
2 | #...........#
3 | ###B#C#B#D###
4 | #A#D#C#A#
5 | #########
6 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/24.txt:
--------------------------------------------------------------------------------
1 | inp w
2 | mul x 0
3 | add x z
4 | mod x 26
5 | div z 1
6 | add x 10
7 | eql x w
8 | eql x 0
9 | mul y 0
10 | add y 25
11 | mul y x
12 | add y 1
13 | mul z y
14 | mul y 0
15 | add y w
16 | add y 2
17 | mul y x
18 | add z y
19 | inp w
20 | mul x 0
21 | add x z
22 | mod x 26
23 | div z 1
24 | add x 14
25 | eql x w
26 | eql x 0
27 | mul y 0
28 | add y 25
29 | mul y x
30 | add y 1
31 | mul z y
32 | mul y 0
33 | add y w
34 | add y 13
35 | mul y x
36 | add z y
37 | inp w
38 | mul x 0
39 | add x z
40 | mod x 26
41 | div z 1
42 | add x 14
43 | eql x w
44 | eql x 0
45 | mul y 0
46 | add y 25
47 | mul y x
48 | add y 1
49 | mul z y
50 | mul y 0
51 | add y w
52 | add y 13
53 | mul y x
54 | add z y
55 | inp w
56 | mul x 0
57 | add x z
58 | mod x 26
59 | div z 26
60 | add x -13
61 | eql x w
62 | eql x 0
63 | mul y 0
64 | add y 25
65 | mul y x
66 | add y 1
67 | mul z y
68 | mul y 0
69 | add y w
70 | add y 9
71 | mul y x
72 | add z y
73 | inp w
74 | mul x 0
75 | add x z
76 | mod x 26
77 | div z 1
78 | add x 10
79 | eql x w
80 | eql x 0
81 | mul y 0
82 | add y 25
83 | mul y x
84 | add y 1
85 | mul z y
86 | mul y 0
87 | add y w
88 | add y 15
89 | mul y x
90 | add z y
91 | inp w
92 | mul x 0
93 | add x z
94 | mod x 26
95 | div z 26
96 | add x -13
97 | eql x w
98 | eql x 0
99 | mul y 0
100 | add y 25
101 | mul y x
102 | add y 1
103 | mul z y
104 | mul y 0
105 | add y w
106 | add y 3
107 | mul y x
108 | add z y
109 | inp w
110 | mul x 0
111 | add x z
112 | mod x 26
113 | div z 26
114 | add x -7
115 | eql x w
116 | eql x 0
117 | mul y 0
118 | add y 25
119 | mul y x
120 | add y 1
121 | mul z y
122 | mul y 0
123 | add y w
124 | add y 6
125 | mul y x
126 | add z y
127 | inp w
128 | mul x 0
129 | add x z
130 | mod x 26
131 | div z 1
132 | add x 11
133 | eql x w
134 | eql x 0
135 | mul y 0
136 | add y 25
137 | mul y x
138 | add y 1
139 | mul z y
140 | mul y 0
141 | add y w
142 | add y 5
143 | mul y x
144 | add z y
145 | inp w
146 | mul x 0
147 | add x z
148 | mod x 26
149 | div z 1
150 | add x 10
151 | eql x w
152 | eql x 0
153 | mul y 0
154 | add y 25
155 | mul y x
156 | add y 1
157 | mul z y
158 | mul y 0
159 | add y w
160 | add y 16
161 | mul y x
162 | add z y
163 | inp w
164 | mul x 0
165 | add x z
166 | mod x 26
167 | div z 1
168 | add x 13
169 | eql x w
170 | eql x 0
171 | mul y 0
172 | add y 25
173 | mul y x
174 | add y 1
175 | mul z y
176 | mul y 0
177 | add y w
178 | add y 1
179 | mul y x
180 | add z y
181 | inp w
182 | mul x 0
183 | add x z
184 | mod x 26
185 | div z 26
186 | add x -4
187 | eql x w
188 | eql x 0
189 | mul y 0
190 | add y 25
191 | mul y x
192 | add y 1
193 | mul z y
194 | mul y 0
195 | add y w
196 | add y 6
197 | mul y x
198 | add z y
199 | inp w
200 | mul x 0
201 | add x z
202 | mod x 26
203 | div z 26
204 | add x -9
205 | eql x w
206 | eql x 0
207 | mul y 0
208 | add y 25
209 | mul y x
210 | add y 1
211 | mul z y
212 | mul y 0
213 | add y w
214 | add y 3
215 | mul y x
216 | add z y
217 | inp w
218 | mul x 0
219 | add x z
220 | mod x 26
221 | div z 26
222 | add x -13
223 | eql x w
224 | eql x 0
225 | mul y 0
226 | add y 25
227 | mul y x
228 | add y 1
229 | mul z y
230 | mul y 0
231 | add y w
232 | add y 7
233 | mul y x
234 | add z y
235 | inp w
236 | mul x 0
237 | add x z
238 | mod x 26
239 | div z 26
240 | add x -9
241 | eql x w
242 | eql x 0
243 | mul y 0
244 | add y 25
245 | mul y x
246 | add y 1
247 | mul z y
248 | mul y 0
249 | add y w
250 | add y 9
251 | mul y x
252 | add z y
253 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/25.txt:
--------------------------------------------------------------------------------
1 | v...>>.vv>
2 | .vv>>.vv..
3 | >>.>v>...v
4 | >>v>>.>.v.
5 | v>v.vv.v..
6 | >.>>..v...
7 | .vv..>.>v.
8 | v.v..>>v.v
9 | ....v..v.>
10 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/3.txt:
--------------------------------------------------------------------------------
1 | 00100
2 | 11110
3 | 10110
4 | 10111
5 | 10101
6 | 01111
7 | 00111
8 | 11100
9 | 10000
10 | 11001
11 | 00010
12 | 01010
13 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/4.txt:
--------------------------------------------------------------------------------
1 | 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
2 |
3 | 22 13 17 11 0
4 | 8 2 23 4 24
5 | 21 9 14 16 7
6 | 6 10 3 18 5
7 | 1 12 20 15 19
8 |
9 | 3 15 0 2 22
10 | 9 18 13 17 5
11 | 19 8 7 25 23
12 | 20 11 10 24 4
13 | 14 21 16 12 6
14 |
15 | 14 21 17 24 4
16 | 10 16 15 9 19
17 | 18 8 23 26 20
18 | 22 11 13 6 5
19 | 2 0 12 3 7
20 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/5.txt:
--------------------------------------------------------------------------------
1 | 0,9 -> 5,9
2 | 8,0 -> 0,8
3 | 9,4 -> 3,4
4 | 2,2 -> 2,1
5 | 7,0 -> 7,4
6 | 6,4 -> 2,0
7 | 0,9 -> 2,9
8 | 3,4 -> 1,4
9 | 0,0 -> 8,8
10 | 5,5 -> 8,2
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/6.txt:
--------------------------------------------------------------------------------
1 | 3,4,3,1,2
2 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/7.txt:
--------------------------------------------------------------------------------
1 | 16,1,2,0,4,2,7,1,2,14
2 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/8.txt:
--------------------------------------------------------------------------------
1 | be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
2 | edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
3 | fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
4 | fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
5 | aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
6 | fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
7 | dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
8 | bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
9 | egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
10 | gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2021/9.txt:
--------------------------------------------------------------------------------
1 | 2199943210
2 | 3987894921
3 | 9856789892
4 | 8767896789
5 | 9899965678
6 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/1.txt:
--------------------------------------------------------------------------------
1 | 1000
2 | 2000
3 | 3000
4 |
5 | 4000
6 |
7 | 5000
8 | 6000
9 |
10 | 7000
11 | 8000
12 | 9000
13 |
14 | 10000
15 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/10.txt:
--------------------------------------------------------------------------------
1 | addx 15
2 | addx -11
3 | addx 6
4 | addx -3
5 | addx 5
6 | addx -1
7 | addx -8
8 | addx 13
9 | addx 4
10 | noop
11 | addx -1
12 | addx 5
13 | addx -1
14 | addx 5
15 | addx -1
16 | addx 5
17 | addx -1
18 | addx 5
19 | addx -1
20 | addx -35
21 | addx 1
22 | addx 24
23 | addx -19
24 | addx 1
25 | addx 16
26 | addx -11
27 | noop
28 | noop
29 | addx 21
30 | addx -15
31 | noop
32 | noop
33 | addx -3
34 | addx 9
35 | addx 1
36 | addx -3
37 | addx 8
38 | addx 1
39 | addx 5
40 | noop
41 | noop
42 | noop
43 | noop
44 | noop
45 | addx -36
46 | noop
47 | addx 1
48 | addx 7
49 | noop
50 | noop
51 | noop
52 | addx 2
53 | addx 6
54 | noop
55 | noop
56 | noop
57 | noop
58 | noop
59 | addx 1
60 | noop
61 | noop
62 | addx 7
63 | addx 1
64 | noop
65 | addx -13
66 | addx 13
67 | addx 7
68 | noop
69 | addx 1
70 | addx -33
71 | noop
72 | noop
73 | noop
74 | addx 2
75 | noop
76 | noop
77 | noop
78 | addx 8
79 | noop
80 | addx -1
81 | addx 2
82 | addx 1
83 | noop
84 | addx 17
85 | addx -9
86 | addx 1
87 | addx 1
88 | addx -3
89 | addx 11
90 | noop
91 | noop
92 | addx 1
93 | noop
94 | addx 1
95 | noop
96 | noop
97 | addx -13
98 | addx -19
99 | addx 1
100 | addx 3
101 | addx 26
102 | addx -30
103 | addx 12
104 | addx -1
105 | addx 3
106 | addx 1
107 | noop
108 | noop
109 | noop
110 | addx -9
111 | addx 18
112 | addx 1
113 | addx 2
114 | noop
115 | noop
116 | addx 9
117 | noop
118 | noop
119 | noop
120 | addx -1
121 | addx 2
122 | addx -37
123 | addx 1
124 | addx 3
125 | noop
126 | addx 15
127 | addx -21
128 | addx 22
129 | addx -6
130 | addx 1
131 | noop
132 | addx 2
133 | addx 1
134 | noop
135 | addx -10
136 | noop
137 | noop
138 | addx 20
139 | addx 1
140 | addx 2
141 | addx 2
142 | addx -6
143 | addx -11
144 | noop
145 | noop
146 | noop
147 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/11.txt:
--------------------------------------------------------------------------------
1 | Monkey 0:
2 | Starting items: 79, 98
3 | Operation: new = old * 19
4 | Test: divisible by 23
5 | If true: throw to monkey 2
6 | If false: throw to monkey 3
7 |
8 | Monkey 1:
9 | Starting items: 54, 65, 75, 74
10 | Operation: new = old + 6
11 | Test: divisible by 19
12 | If true: throw to monkey 2
13 | If false: throw to monkey 0
14 |
15 | Monkey 2:
16 | Starting items: 79, 60, 97
17 | Operation: new = old * old
18 | Test: divisible by 13
19 | If true: throw to monkey 1
20 | If false: throw to monkey 3
21 |
22 | Monkey 3:
23 | Starting items: 74
24 | Operation: new = old + 3
25 | Test: divisible by 17
26 | If true: throw to monkey 0
27 | If false: throw to monkey 1
28 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/12.txt:
--------------------------------------------------------------------------------
1 | Sabqponm
2 | abcryxxl
3 | accszExk
4 | acctuvwj
5 | abdefghi
6 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/13.txt:
--------------------------------------------------------------------------------
1 | [1,1,3,1,1]
2 | [1,1,5,1,1]
3 |
4 | [[1],[2,3,4]]
5 | [[1],4]
6 |
7 | [9]
8 | [[8,7,6]]
9 |
10 | [[4,4],4,4]
11 | [[4,4],4,4,4]
12 |
13 | [7,7,7,7]
14 | [7,7,7]
15 |
16 | []
17 | [3]
18 |
19 | [[[]]]
20 | [[]]
21 |
22 | [1,[2,[3,[4,[5,6,7]]]],8,9]
23 | [1,[2,[3,[4,[5,6,0]]]],8,9]
24 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/14.txt:
--------------------------------------------------------------------------------
1 | 498,4 -> 498,6 -> 496,6
2 | 503,4 -> 502,4 -> 502,9 -> 494,9
3 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/15.txt:
--------------------------------------------------------------------------------
1 | Sensor at x=2, y=18: closest beacon is at x=-2, y=15
2 | Sensor at x=9, y=16: closest beacon is at x=10, y=16
3 | Sensor at x=13, y=2: closest beacon is at x=15, y=3
4 | Sensor at x=12, y=14: closest beacon is at x=10, y=16
5 | Sensor at x=10, y=20: closest beacon is at x=10, y=16
6 | Sensor at x=14, y=17: closest beacon is at x=10, y=16
7 | Sensor at x=8, y=7: closest beacon is at x=2, y=10
8 | Sensor at x=2, y=0: closest beacon is at x=2, y=10
9 | Sensor at x=0, y=11: closest beacon is at x=2, y=10
10 | Sensor at x=20, y=14: closest beacon is at x=25, y=17
11 | Sensor at x=17, y=20: closest beacon is at x=21, y=22
12 | Sensor at x=16, y=7: closest beacon is at x=15, y=3
13 | Sensor at x=14, y=3: closest beacon is at x=15, y=3
14 | Sensor at x=20, y=1: closest beacon is at x=15, y=3
15 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/16.txt:
--------------------------------------------------------------------------------
1 | Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
2 | Valve BB has flow rate=13; tunnels lead to valves CC, AA
3 | Valve CC has flow rate=2; tunnels lead to valves DD, BB
4 | Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
5 | Valve EE has flow rate=3; tunnels lead to valves FF, DD
6 | Valve FF has flow rate=0; tunnels lead to valves EE, GG
7 | Valve GG has flow rate=0; tunnels lead to valves FF, HH
8 | Valve HH has flow rate=22; tunnel leads to valve GG
9 | Valve II has flow rate=0; tunnels lead to valves AA, JJ
10 | Valve JJ has flow rate=21; tunnel leads to valve II
11 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/17.txt:
--------------------------------------------------------------------------------
1 | >>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
2 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/18.txt:
--------------------------------------------------------------------------------
1 | 2,2,2
2 | 1,2,2
3 | 3,2,2
4 | 2,1,2
5 | 2,3,2
6 | 2,2,1
7 | 2,2,3
8 | 2,2,4
9 | 2,2,6
10 | 1,2,5
11 | 3,2,5
12 | 2,1,5
13 | 2,3,5
14 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/19.txt:
--------------------------------------------------------------------------------
1 | Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
2 | Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.
3 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/2.txt:
--------------------------------------------------------------------------------
1 | A Y
2 | B X
3 | C Z
4 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/20.txt:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | -3
4 | 3
5 | -2
6 | 0
7 | 4
8 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/21.txt:
--------------------------------------------------------------------------------
1 | root: pppw + sjmn
2 | dbpl: 5
3 | cczh: sllz + lgvd
4 | zczc: 2
5 | ptdq: humn - dvpt
6 | dvpt: 3
7 | lfqf: 4
8 | humn: 5
9 | ljgn: 2
10 | sjmn: drzm * dbpl
11 | sllz: 4
12 | pppw: cczh / lfqf
13 | lgvd: ljgn * ptdq
14 | drzm: hmdt - zczc
15 | hmdt: 32
16 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/22.txt:
--------------------------------------------------------------------------------
1 | ...#
2 | .#..
3 | #...
4 | ....
5 | ...#.......#
6 | ........#...
7 | ..#....#....
8 | ..........#.
9 | ...#....
10 | .....#..
11 | .#......
12 | ......#.
13 |
14 | 10R5L5R10L4R5L5
15 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/23.txt:
--------------------------------------------------------------------------------
1 | ....#..
2 | ..###.#
3 | #...#.#
4 | .#...##
5 | #.###..
6 | ##.#.##
7 | .#..#..
8 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/24.txt:
--------------------------------------------------------------------------------
1 | #.######
2 | #>>.<^<#
3 | #.<..<<#
4 | #>v.><>#
5 | #<^v^^>#
6 | ######.#
7 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/25.txt:
--------------------------------------------------------------------------------
1 | 1=-0-2
2 | 12111
3 | 2=0=
4 | 21
5 | 2=01
6 | 111
7 | 20012
8 | 112
9 | 1=-1=
10 | 1-12
11 | 12
12 | 1=
13 | 122
14 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/3.txt:
--------------------------------------------------------------------------------
1 | vJrwpWtwJgWrhcsFMMfFFhFp
2 | jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
3 | PmmdzqPrVvPwwTWBwg
4 | wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
5 | ttgJtRGJQctTZtZT
6 | CrZsJsPPZsGzwwsLwLmpwMDw
7 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/4.txt:
--------------------------------------------------------------------------------
1 | 2-4,6-8
2 | 2-3,4-5
3 | 5-7,7-9
4 | 2-8,3-7
5 | 6-6,4-6
6 | 2-6,4-8
7 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/5.txt:
--------------------------------------------------------------------------------
1 | [D]
2 | [N] [C]
3 | [Z] [M] [P]
4 | 1 2 3
5 |
6 | move 1 from 2 to 1
7 | move 3 from 1 to 3
8 | move 2 from 2 to 1
9 | move 1 from 1 to 2
10 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/6.txt:
--------------------------------------------------------------------------------
1 | mjqjpqmgbljsphdztnvjfqwrcgsmlb
2 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/7.txt:
--------------------------------------------------------------------------------
1 | $ cd /
2 | $ ls
3 | dir a
4 | 14848514 b.txt
5 | 8504156 c.dat
6 | dir d
7 | $ cd a
8 | $ ls
9 | dir e
10 | 29116 f
11 | 2557 g
12 | 62596 h.lst
13 | $ cd e
14 | $ ls
15 | 584 i
16 | $ cd ..
17 | $ cd ..
18 | $ cd d
19 | $ ls
20 | 4060174 j
21 | 8033020 d.log
22 | 5626152 d.ext
23 | 7214296 k
24 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/8.txt:
--------------------------------------------------------------------------------
1 | 30373
2 | 25512
3 | 65332
4 | 33549
5 | 35390
6 |
--------------------------------------------------------------------------------
/src/assets/inputs/2022/9.txt:
--------------------------------------------------------------------------------
1 | R 5
2 | U 8
3 | L 8
4 | D 3
5 | R 17
6 | D 10
7 | L 25
8 | U 20
9 |
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RaczeQ/AdventOfCodeAngular/d0a64b2f29a94ea0818e8873aecfb1827f1cfb5a/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AdventOfCode
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 | import './app/helper/util-functions/extensions';
7 |
8 | if (environment.production) {
9 | enableProdMode();
10 | }
11 |
12 | platformBrowserDynamic()
13 | .bootstrapModule(AppModule)
14 | .catch((err) => console.error(err));
15 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including
12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | /***************************************************************************************************
46 | * Zone JS is required by default for Angular itself.
47 | */
48 | import 'zone.js'; // Included with Angular CLI.
49 |
50 |
51 | /***************************************************************************************************
52 | * APPLICATION IMPORTS
53 | */
54 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | // First, initialize the Angular testing environment.
11 | getTestBed().initTestEnvironment(
12 | BrowserDynamicTestingModule,
13 | platformBrowserDynamicTesting(),
14 | );
15 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "strict": true,
9 | "noImplicitOverride": true,
10 | "noPropertyAccessFromIndexSignature": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "sourceMap": true,
14 | "declaration": false,
15 | "downlevelIteration": true,
16 | "experimentalDecorators": true,
17 | "moduleResolution": "node",
18 | "importHelpers": true,
19 | "target": "ES2022",
20 | "module": "es2020",
21 | "lib": ["es2020", "dom"],
22 | "useDefineForClassFields": false,
23 | "allowJs": true
24 | },
25 | "angularCompilerOptions": {
26 | "enableI18nLegacyMessageIdFormat": false,
27 | "strictInjectionParameters": true,
28 | "strictInputAccessModifiers": true,
29 | "strictTemplates": true
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/tsconfig.worker.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/worker",
6 | "lib": [
7 | "es2020",
8 | "webworker"
9 | ],
10 | "types": []
11 | },
12 | "include": [
13 | "src/**/*.worker.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------