Skip to content

Commit 63c40f6

Browse files
committed
Added 2017 day 04
1 parent 8d620f8 commit 63c40f6

3 files changed

Lines changed: 97 additions & 0 deletions

File tree

2017/04/code.mjs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { delay, Console } from "../../utility.mjs";
2+
3+
export default class {
4+
/**
5+
* @param {Console} solConsole Solution console.
6+
* @param {HTMLElement} visContainer Visualization container.
7+
*/
8+
constructor(solConsole, visContainer) {
9+
this.isSolving = false;
10+
this.isStopping = false;
11+
this.solConsole = typeof solConsole !== "undefined" ? solConsole : new Console();
12+
this.visContainer = visContainer;
13+
}
14+
15+
/**
16+
* Parses the puzzle input.
17+
* @param {string} input Puzzle input.
18+
* @returns {string[][]} Passphrases.
19+
*/
20+
parse(input) {
21+
let consoleLine = this.solConsole.addLine("Parsing...");
22+
23+
let passphrases = input.trim().split(/\r?\n/).map((line, index) => {
24+
if (!/^[\sa-z]+$/.test(line))
25+
throw new Error(`Invalid data in line ${index + 1}`);
26+
return line.split(" ");
27+
});
28+
29+
consoleLine.innerHTML += " done.";
30+
return passphrases;
31+
}
32+
33+
34+
/**
35+
* Finds the number of valid passphrases.
36+
* @param {number} part Puzzle part.
37+
* @param {string} input Puzzle input.
38+
* @param {boolean} visualization Enable visualization.
39+
* @returns {number} Number of valid passphrases.
40+
*/
41+
async solve(part, input, visualization) {
42+
try {
43+
this.isSolving = true;
44+
45+
let passphrases = this.parse(input);
46+
47+
let visConsole = new Console();
48+
if (visualization)
49+
this.visContainer.append(visConsole.container);
50+
51+
let numberOfValidPassphrases = 0;
52+
for (let passphrase of passphrases) {
53+
let passphraseWithSortedWords = passphrase.map(e => e.split("").sort().join(""))
54+
let invalidWordIndexPair = null;
55+
for (let i = 0; i < passphrase.length && invalidWordIndexPair == null; i++) {
56+
for (let j = i + 1; j < passphrase.length && invalidWordIndexPair == null; j++) {
57+
if ((part == 1 && passphrase[i] == passphrase[j]) || (part == 2 && passphraseWithSortedWords[i] == passphraseWithSortedWords[j]))
58+
invalidWordIndexPair = [i, j];
59+
}
60+
}
61+
62+
if (invalidWordIndexPair == null)
63+
numberOfValidPassphrases++;
64+
65+
if (visualization) {
66+
visConsole.addLine(passphrase.map((e, i) =>
67+
invalidWordIndexPair == null ? `<span class="highlighted">${e}</span>` : (invalidWordIndexPair.indexOf(i) >= 0 ? `<span class="error">${e}</span>` : e)).join(" "));
68+
visConsole.addLine();
69+
}
70+
}
71+
72+
return numberOfValidPassphrases;
73+
}
74+
75+
finally {
76+
this.isSolving = false;
77+
}
78+
}
79+
80+
/**
81+
* Stops solving the puzzle.
82+
*/
83+
async stopSolving() {
84+
this.isStopping = true;
85+
while (this.isSolving)
86+
await(delay(10));
87+
this.isStopping = false;
88+
}
89+
}

2017/04/testInput.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
aa bb cc dd ee
2+
aa bb cc dd aa
3+
aa bb cc dd aaa
4+
abcde xyz ecdab

tree.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ export const years = [
410410
{
411411
name: "Day 3: Spiral Memory", path: "./2017/03", taskUrl: "https://adventofcode.com/2017/day/3",
412412
answers: {part1: 31, part2: 1968}
413+
},
414+
{
415+
name: "Day 4: High-Entropy Passphrases", path: "./2017/04", taskUrl: "https://adventofcode.com/2017/day/4",
416+
answers: {part1: 3, part2: 2}
413417
}
414418
]
415419
},

0 commit comments

Comments
 (0)