Skip to main content
attempted to explain the code - sorry but i'm not very good at explanations
Source Link
Andy
  • 131
  • 3

the code reuses the 'blot' method to calculate the path length. variables

variables/methods:

Attempt at more detailed explanation:

make a copy of the input string, which we use for finding the length of the path from any given point in the map.

z = s.dup

define a 'ps' (path length) anonymous function (lambda) which takes the map index i as an argument. it returns the length of the path from that point. it does this by calling the 'b' (blot) method to insert x's on a copy of the original map and then counting the number of x's in the returned string.

  ps = ->(i){b(z.dup,i).scan('x').size}

the following part iterates over each character in the map (index i, character s[i]). it calls the 'b' (blot) function on map position i if the path length from position i is greater than 2, and if it's not a space or newline character.

  (0...s.size).each { |i|
     b(s, i) if ![' ',"\n"].include?(s[i]) && ps.call(i) > 2
  }

the b (blot) function takes the map string and an index as argument. it initialises @v (visited array) and calls the b2 helper function.

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end

the b2 function takes the map string, a map position (i), and a character in the current path (c). it calls itself recursively to replace connected sections of digits with the 'x' character. it returns the input string (this is so the ps function can call scan() on the return value).

this if statement is checking that the map position (i) given is within the bounds of the string (0...s.size) and that the character at s[i] is the same as the starting character. also @v[i] is checked to avoid infinite recursion.

if(0...s.size) === i && s[i] == c && !@v[i]

this is the bit that replaces the character at index (i) with the 'x' character. it also marks that index as visited.

@v[i] = s[i] = 'x'

this is where b2 calls itself recursively searching for the path. i+1 is one character to the right, i-1 is one character to the left, i+6 is one row down (5 digits + 1 newline = 6 characters), i-6 is one row up.

[1,-1,6,-6].each { |j| b2(s, i+j, c) }

the code reuses the 'blot' method to calculate the path length. variables/methods:

the code reuses the 'blot' method to calculate the path length.

variables/methods:

Attempt at more detailed explanation:

make a copy of the input string, which we use for finding the length of the path from any given point in the map.

z = s.dup

define a 'ps' (path length) anonymous function (lambda) which takes the map index i as an argument. it returns the length of the path from that point. it does this by calling the 'b' (blot) method to insert x's on a copy of the original map and then counting the number of x's in the returned string.

  ps = ->(i){b(z.dup,i).scan('x').size}

the following part iterates over each character in the map (index i, character s[i]). it calls the 'b' (blot) function on map position i if the path length from position i is greater than 2, and if it's not a space or newline character.

  (0...s.size).each { |i|
     b(s, i) if ![' ',"\n"].include?(s[i]) && ps.call(i) > 2
  }

the b (blot) function takes the map string and an index as argument. it initialises @v (visited array) and calls the b2 helper function.

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end

the b2 function takes the map string, a map position (i), and a character in the current path (c). it calls itself recursively to replace connected sections of digits with the 'x' character. it returns the input string (this is so the ps function can call scan() on the return value).

this if statement is checking that the map position (i) given is within the bounds of the string (0...s.size) and that the character at s[i] is the same as the starting character. also @v[i] is checked to avoid infinite recursion.

if(0...s.size) === i && s[i] == c && !@v[i]

this is the bit that replaces the character at index (i) with the 'x' character. it also marks that index as visited.

@v[i] = s[i] = 'x'

this is where b2 calls itself recursively searching for the path. i+1 is one character to the right, i-1 is one character to the left, i+6 is one row down (5 digits + 1 newline = 6 characters), i-6 is one row up.

[1,-1,6,-6].each { |j| b2(s, i+j, c) }
Source Link
Andy
  • 131
  • 3

Ruby, 304 bytes

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end
def b2(s,i,c)
  if(0...s.size)===i&&s[i]==c&&!@v[i]
    @v[i]=s[i]='x'
    [1,-1,6,-6].each{|j|b2(s,i+j,c)}
  end
  s
end
def f(s)
  z = s.dup
  ps = ->(i){b(z.dup,i).scan('x').size}
  (0...s.size).each{|i|b(s, i)if ![' ',"\n"].include?(s[i])&&ps.call(i)>2}
  s
end

example usage:

puts f(File.read("map.txt"))

the code reuses the 'blot' method to calculate the path length. variables/methods:

  • f(s): function to convert map string, returns new map with 'x's
  • ps(i): path size from map index i (where x = i % 6, y = i / 6)
  • s: input string, map lines separated by "\n"
  • z: copy of input string
  • b(s,i): 'blot' function: writes 'x' from map index i over paths
  • @v: 'visited' array