Day 13 Part 2

Summary

See Part 1

The twist is that one # or . should be the opposite on every pattern; Fixing that error will make a new reflection point. The goal is to fix the error and get the sum like Part 1

Smudges

Luckily this challenge doesn’t seem that bad as I can reuse the contents of get_reflection_points() and slightly tweak it.

First of all I need to keep track of amount of “smudges” I fix, it can’t be more than 1 for every potential reflection. Secondly I need to break up the pattern into a nested array format: string[][]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function get_reflection_points(contents: string[]): number[]{
  const contents_len: number = contents.length;
  const contents_arr: string[][] = contents.map((ele) => ele.split(''));
  return contents
    .map((ele, index) => {
      let flipped_count: number = 0;
      //...etc
    })
    .filter((ele) => ele != -1);
}

Helper

The next step is to write a function that will tell us if two rows are “smudge-able”, ie they have exactly a 1 char difference.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function has_single_difference(a: string[], b: string[]): boolean{
  let difference_count: number = 0;
  for (let i = 0; i < a.length; i++){
    if (a[i] !== b[i]){
      difference_count++;
      if (difference_count > 1){
        return false;
      }
    }
  };
  return true;
}

Case 1

The smudge I go after first will be the ones that are on the reflection point. By changing the logic of the first if in the map and by using our helper function from the previous section should solve this case

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
contents
  .map((ele, index) => {
    if (index == contents.length - 1){
      return -1;
    }

    let flipped_count: number = 0;
    let reflection_match: boolean = false;
    if (ele === contents[index+1]){
      // exact match
      reflection_match = true
    }else{
      if (has_single_difference(contents_arr[index], contents_arr[index+1])){
        reflection_match = true;
        flipped_count++; // record we 'changed' a value
      }
    }

    if (reflection_match){
      // ..etc
      return index;
    }
    return -1;
  })
  .filter((ele) => ele != -1);

Case 2

The second smudge type would be one that isn’t directly touching the reflection points. To do this I edit the reflection point validation to also use our helper function. This will use the exact same logic as in case 1, but it needs to check that if a char is flipped in case 1 it can’t be flipped in case 2.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
contents
  .map((ele, index) => {
  
    //.. etc
    
    if (reflection_match){
      // -1 to account for len-1 and -1 for reflect
      const rows_below: number = contents_len - index - 2;
      // grab the lowest one
      const rows_to_check: number = index < rows_below ? index : rows_below;

      for (let i = 0; i < rows_to_check; i++){
        if (contents[index-(1+i)] !== contents[index+(2+i)]){

          if (
            flipped_count == 0 &&
            has_single_difference(
              contents_arr[index-(1+i)],
              contents_arr[index+(2+i)]
            )
          ){
            flipped_count++; // record we 'changed' a value
          }else{
            return -1;
          }
        }
      };
      if (flipped_count){
        return index;
      }else{
        return -1;
      }
    }
  })
  .filter((ele) => ele != -1);

Final

Putting all these pieces together would look like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
function has_single_difference(a: string[], b: string[]): boolean{
  let difference_count: number = 0;
  for (let i = 0; i < a.length; i++){
    if (a[i] !== b[i]){
      difference_count++;
      if (difference_count > 1){
        return false;
      }
    }
  };
  return true;
}

function get_reflection_points(contents: string[]): number[]{
  const contents_len: number = contents.length;
  const contents_arr: string[][] = contents.map((ele) => ele.split(''))
  return contents
    .map((ele, index) => {
      if (index == contents.length - 1){
        return -1;
      }

      let flipped_count: number = 0;
      let reflection_match: boolean = false;
      if (ele === contents[index+1]){
        reflection_match = true
      }else{
        if (has_single_difference(contents_arr[index], contents_arr[index+1])){
          reflection_match = true;
          flipped_count++; // record we 'changed' a value
        }
      }

      if (reflection_match){
        // -1 to account for len-1 and -1 for reflect
        const rows_below: number = contents_len - index - 2;
        // grab the lowest one
        const rows_to_check: number = index < rows_below ? index : rows_below;

        for (let i = 0; i < rows_to_check; i++){
          if (contents[index-(1+i)] !== contents[index+(2+i)]){

            if (
              flipped_count == 0 &&
              has_single_difference(
                contents_arr[index-(1+i)],
                contents_arr[index+(2+i)]
              )
            ){
              flipped_count++; // record we 'changed' a value
            }else{
              return -1;
            }
          }
        };
        if (flipped_count){
          return index;
        }else{
          return -1;
        }
      }
      return -1;
    })
    .filter((ele) => ele != -1);
}

function get_vertical(horizontal: string[]): string[]{
  let vertical: string[] = [];
  let vertical_count: number = -1;
  horizontal.forEach((row) => {
    row.split('').forEach((cell, index) => {
      if (vertical_count < index){
        vertical.push(cell);
        vertical_count++;
      }else{
        vertical[index] = cell + vertical[index];
      }
    });
  });
  return vertical;
}

const puzzle_list: string[][]; // filled from file

let horizontal: number = 0;
let vertical: number = 0;
puzzle_list.forEach((puzzle) => {
  let horiz: number[] = get_reflection_points(puzzle);
  if (horiz.length){ horizontal += horiz[0] }
  
  let vert: number[] = get_reflection_points(get_vertical(puzzle));
  if (vert.length){ vertical += vert[0] }
});

console.log(`Answer => ${vertical + (100 * horizontal)}`);
comments powered by Disqus