Mercurial > repos > other > adventofcode2023
view day7b.rb @ 28:5ba34a851816
Implement Day 19 workflows, skip part 2
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Wed, 03 Jan 2024 11:34:54 +0000 |
parents | 9ec95ff0d33d |
children |
line wrap: on
line source
#! /usr/bin/env ruby require 'set' if ARGV.length != 1 abort("Incorrect arguments - needs input file") elsif not File.exist? (ARGV[0]) abort("File #{ARGV[0]} did not exist") end file = ARGV[0] Hand = Struct.new(:cards, :score, :bid) $card_scoring = ["J"].concat(("2".."9").to_a).concat(["T", "J", "Q", "K", "A"]) JOKER_VALUE = $card_scoring.index("J") FULL_HOUSE = Set.new([2,3]) TWO_PAIR = {2 => 2, 1 => 1} def score_hand(cards) card_vals = cards.each_char.map {|c| $card_scoring.index(c)} card_groups = card_vals.group_by{|v| v}.sort {|a,b| # Push jokers to the start so that we can find the biggest group # to add them to if a[0] == JOKER_VALUE then -1 elsif b[0] == JOKER_VALUE then 1 # Then order by number of values elsif a[1].length < b[1].length then -1 elsif a[1].length > b[1].length then 1 # Then order by card score else a[0] <=> b[0] end } jokers = card_vals.count(JOKER_VALUE) joker_replacement = card_groups.last[0] card_counts = card_groups.map {|v| # If it's the joker replacement, add the number of jokers (which may be 0) if v[0] == joker_replacement and v[0] != JOKER_VALUE then v[1].length + jokers # If it's the jokers and we're not a hand of jokers then remove them - they're added elsewhere elsif v[0] == JOKER_VALUE and joker_replacement != JOKER_VALUE then 0 # Else just take the count else v[1].length end }.select {|num| num != 0} card_count_counts = card_counts.group_by{|v| v}.map{|k,v| [k, v.length]}.to_h dejokered_card_vals = card_vals.map {|v| v == 0 ? card_vals.max : v} of_a_kind = card_counts.max rank = of_a_kind * 10 # 5, 4 or 3 of a kind or a pair if Set.new(card_counts) == FULL_HOUSE rank = 35 elsif card_count_counts == TWO_PAIR rank = 25 end card_vals.reduce("#{rank}") {|str, v| "#{str}.#{(v+1).to_s.rjust(2, '0')}"} end hands = File.open(file, "r").each_line(chomp: true).map {|line| cards, bid = line.split(" "); Hand.new(cards, score_hand(cards), bid.to_i)} puts hands.sort {|a, b| a.score <=> b.score}.map.with_index(1) {|val, i| puts "#{val}"; i * val.bid}.sum # Rest of algorithm here