Giter VIP home page Giter VIP logo

aoc23's People

Contributors

blboyle avatar

Watchers

 avatar

aoc23's Issues

Simplify Day 1 example

aoc23/day1/day1.rb

Lines 17 to 113 in c07af48

class CalibrationDocument
NUM_MAP = {
"one": '1',
"two": '2',
"three": '3',
"four": '4',
"five": '5',
"six": '6',
"seven": '7',
"eight": '8',
"nine": '9'
}.freeze
NUMS = %w[
1
2
3
4
5
6
7
8
9
].freeze
NUM_WORDS = %w[one two three four five six seven eight nine].freeze
def initialize(input)
@input = input
end
def convert_to_lines
@input.split
end
def sum_calibration_values
total = 0
convert_to_lines.each do |line|
total += calculate_calibration_value(line)
end
total
end
def sum_calibration_values_with_letters
total = 0
convert_to_lines.each do |line|
total += calculate_calibration_value_with_letters(line)
end
total
end
private
def calculate_calibration_value(line)
regex = /\d/
value = line.scan(regex)
[value[0], value[value.length - 1]].join.to_i
end
def calculate_calibration_value_with_letters(line)
newLine = line
results = []
lengthRemoved = 0
while newLine.length > 1
NUMS.each do |num|
index = newLine.index(num)
results.push([index.to_i + lengthRemoved, num]) unless index.nil?
end
NUM_WORDS.each do |word|
index2 = newLine.index(word)
results.push([index2.to_i + lengthRemoved, word]) unless index2.nil?
end
lengthRemoved += 1
newLine = newLine[1..-1]
end
sorted = results.sort_by { |a| a[0] }
all_numbers = sorted.map do |a|
if a[1].length === 1
a[1].to_i
else
NUM_MAP[a[1].to_sym].to_i
end
end
[all_numbers[0], all_numbers[- 1]].join.to_i
end
end

class CalibrationDocument
  NUMBERS_REGEX = /(\d)*(one)*(two)*(three)*(four)*(five)*(six)*(seven)*(eight)*(nine)*/.freeze
  NUM_MAP = {
    "one": '1',
    "two": '2',
    "three": '3',
    "four": '4',
    "five": '5',
    "six": '6',
    "seven": '7',
    "eight": '8',
    "nine": '9'
  }.freeze


  def initialize(input)
    @input = input
  end


  def sum_calibration_values
    @sum_calibration_values ||= lines.sum { |line| calculate_calibration_value(line) } # use ruby's built in sum method to loop over values and sum them. No need to setup unnecessary variables. Think of blocks like this as JS arrow functions (and remember Ruby was using simple anonymous functions before it was cool :p )

# the @var ||= some_code idiom is a way of lazy loading your code. You only run the calculation when you call this method and only if @var is nil, othewise you just return the already calculated value of @var. Memoization like this can keep you from recomputing expensive calculations. 
  end

  def sum_calibration_values_with_letters
   @sum_calibration_values_with_letters ||= lines.sum { |line| calculate_calibration_value_with_letters(line) } 
  end


  private

  # only expose the parts you care about in your public api, otherwise unwanted dependencies can emerge. 
  def lines 
    @lines ||= @input.split # this allows you to split the input into lines once and never do it again. Also lines makes more sense now because you don't care that its converting, you just care it returns the lines. 
  end

  def calculate_calibration_value(line)
    values = line.scan(/\d/) # This regex is simple enough to just inline it
    "#{values.first}#{values.last}".to_i  
  end

  def calculate_calibration_value_with_letters(line)
    # given "4nineeightseven2" as input 
    numbers = line.
      scan(NUMBERS_REGEX). # the regex will capture each word or number as its own group 
      flatten. # that gives us an array of arrays so we want to flatten it 
      compact. # then we want to remove the nils # => ["4", "nine", "eight", "seven", "2"]
      map { |e| NUM_MAP.fetch(e.to_sym, e) }. # we use fetch here to grab the keys from the map and replace with the number string. The integers are not keys, so we can find 'four' but not '4'. With fetch, if there is no match, the second argument will be a default value. In this case we just pass the 4 through. # =>["4", "9", "8", "7", "2"]

      # last we just grab the first and last element of the array, join them and cast to integers.
    [integers.first, integers.last]. # =>["4", "2"] 
      join. # => "42"
      to_i   #=> 42
      # we can also just do "#{integers.first}#{integers.last}".to_i which I _thing might_ be more performant? Im not actually sure and I have no strong preference either way
  end
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.