2023 day 7
parent
36325259ba
commit
a786488bca
|
@ -2,7 +2,7 @@ FC:=gfortran
|
|||
FFLAGS:=-Wall -Wno-maybe-uninitialized
|
||||
BIN:=./bin
|
||||
SRC:=./src
|
||||
BINS:=./bin/day01.bin ./bin/day01b.bin ./bin/day02.bin ./bin/day03.bin ./bin/day04.bin ./bin/day05.bin ./bin/day05b.bin ./bin/day06.bin
|
||||
BINS:=./bin/day01.bin ./bin/day01b.bin ./bin/day02.bin ./bin/day03.bin ./bin/day04.bin ./bin/day05.bin ./bin/day05b.bin ./bin/day06.bin ./bin/day07.bin ./bin/day07b.bin
|
||||
|
||||
all: aoc19
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483
|
|
@ -0,0 +1,171 @@
|
|||
program day7
|
||||
implicit none
|
||||
integer, parameter :: max_chars = 300
|
||||
character(200) :: fname
|
||||
character(max_chars) :: fline
|
||||
integer :: n_arguments
|
||||
integer, parameter :: max_hands = 2000
|
||||
character(len=5) :: hands(1:max_hands)
|
||||
integer :: bids(1:max_hands)
|
||||
integer :: rank(1:max_hands)
|
||||
integer :: i, i2, n_hands
|
||||
integer :: istat
|
||||
integer :: beats, winnings, total_winnings
|
||||
|
||||
n_arguments = command_argument_count()
|
||||
if (n_arguments .eq. 1) then
|
||||
call get_command_argument(1, fname)
|
||||
print *, "File: ", trim(fname)
|
||||
print *
|
||||
else
|
||||
print *, "Wrong number of arguments: ", n_arguments
|
||||
stop
|
||||
end if
|
||||
|
||||
|
||||
open(10, file=fname)
|
||||
n_hands = 0
|
||||
do i=1, max_hands
|
||||
read(10, "(a)", iostat = istat) fline
|
||||
if ((len_trim(fline) .eq. 0) .or. (is_iostat_end(istat))) then
|
||||
exit
|
||||
end if
|
||||
read(fline, *) hands(i), bids(i)
|
||||
n_hands = n_hands + 1
|
||||
end do
|
||||
close(10)
|
||||
print *, "Number of hands: ", n_hands
|
||||
rank = -1
|
||||
rank(1) = 1
|
||||
print *
|
||||
do i=2,n_hands
|
||||
beats = 0
|
||||
do i2=1,(i-1)
|
||||
if (rank_correct(hands(i), hands(i2))) then
|
||||
! hand i ranks higher than hand i2
|
||||
if (rank(i2) .gt. beats) then
|
||||
beats = rank(i2)
|
||||
end if
|
||||
write(*, 21) i, hands(i), i2, hands(i2)
|
||||
else
|
||||
! hand i ranks lower than hand i2
|
||||
rank(i2) = rank(i2) + 1
|
||||
write(*, 22) i, hands(i), i2, hands(i2)
|
||||
end if
|
||||
end do
|
||||
rank(i) = beats+1
|
||||
end do
|
||||
print *
|
||||
total_winnings = 0
|
||||
do i=1, n_hands
|
||||
winnings = bids(i) * rank(i)
|
||||
write(*, 20) hands(i), bids(i), rank(i), winnings
|
||||
total_winnings = total_winnings + winnings
|
||||
end do
|
||||
print *
|
||||
print *, "Total winnings: ", total_winnings
|
||||
|
||||
20 format("Hand: ", a5, "; Bid: ", i4, "; Rank: ", i4, "; Winnings: ", i8)
|
||||
21 format(i4, " (", a5, ") beats ", i4, " (", a5, ")")
|
||||
22 format(i4, " (", a5, ") beaten by ", i4, " (", a5, ")")
|
||||
|
||||
contains
|
||||
function hand_type(hand)
|
||||
character(len=5), intent(in) :: hand
|
||||
integer :: hand_type
|
||||
character(len=1) :: dist_cards(1:5)
|
||||
integer :: card_count(1:5)
|
||||
integer :: n_dc
|
||||
integer :: i, i2
|
||||
character(len=1) :: this_card
|
||||
logical :: existing_card
|
||||
integer :: sets(1:5)
|
||||
dist_cards = ' '
|
||||
card_count = 0
|
||||
n_dc = 1
|
||||
dist_cards(1) = hand(1:1)
|
||||
card_count(1) = 1
|
||||
do i=2,5
|
||||
this_card = hand(i:i)
|
||||
existing_card = .false.
|
||||
do i2=1,n_dc
|
||||
if (dist_cards(i2) .eq. this_card) then
|
||||
existing_card = .true.
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
if (existing_card) then
|
||||
card_count(i2) = card_count(i2) + 1
|
||||
else
|
||||
n_dc = n_dc + 1
|
||||
card_count(n_dc) = 1
|
||||
dist_cards(n_dc) = this_card
|
||||
end if
|
||||
end do
|
||||
sets = 0
|
||||
do i=1,n_dc
|
||||
sets(card_count(i)) = sets(card_count(i)) + 1
|
||||
end do
|
||||
if (sets(5) .eq. 1) then
|
||||
! Five of a kind
|
||||
hand_type = 7
|
||||
else if (sets(4) .eq. 1) then
|
||||
! Four of a kind
|
||||
hand_type = 6
|
||||
else if ((sets(3) .eq. 1) .and. (sets(2) .eq. 1)) then
|
||||
! Full house
|
||||
hand_type = 5
|
||||
else if (sets(3) .eq. 1) then
|
||||
! Three of a kind
|
||||
hand_type = 4
|
||||
else if (sets(2) .eq. 2) then
|
||||
! Two pair
|
||||
hand_type = 3
|
||||
else if (sets(2) .eq. 1) then
|
||||
! One pair
|
||||
hand_type = 2
|
||||
else
|
||||
! High card
|
||||
hand_type = 1
|
||||
end if
|
||||
end function hand_type
|
||||
|
||||
function tiebreak(hand1, hand2)
|
||||
! True if hand1 would tiebreak ahead of hand2
|
||||
implicit none
|
||||
character(len=5), intent(in) :: hand1, hand2
|
||||
logical :: tiebreak
|
||||
character(len=13) :: cards = "23456789TJQKA"
|
||||
integer :: pos_1, pos_2, i
|
||||
do i=1,5
|
||||
pos_1 = scan(cards, hand1(i:i))
|
||||
pos_2 = scan(cards, hand2(i:i))
|
||||
if (pos_1 .lt. pos_2) then
|
||||
tiebreak = .false.
|
||||
return
|
||||
else if (pos_1 .gt. pos_2) then
|
||||
tiebreak = .true.
|
||||
return
|
||||
end if
|
||||
end do
|
||||
tiebreak = .true.
|
||||
end function tiebreak
|
||||
|
||||
function rank_correct(hand1, hand2)
|
||||
implicit none
|
||||
character(len=5), intent(in) :: hand1, hand2
|
||||
logical :: rank_correct
|
||||
integer :: h1_type, h2_type
|
||||
h1_type = hand_type(hand1)
|
||||
h2_type = hand_type(hand2)
|
||||
if (h1_type .gt. h2_type) then
|
||||
rank_correct = .true.
|
||||
else if (h1_type .lt. h2_type) then
|
||||
rank_correct = .false.
|
||||
else
|
||||
rank_correct = tiebreak(hand1, hand2)
|
||||
end if
|
||||
end function rank_correct
|
||||
|
||||
|
||||
end program day7
|
|
@ -0,0 +1,188 @@
|
|||
program day7b
|
||||
implicit none
|
||||
integer, parameter :: max_chars = 300
|
||||
character(200) :: fname
|
||||
character(max_chars) :: fline
|
||||
integer :: n_arguments
|
||||
integer, parameter :: max_hands = 2000
|
||||
character(len=5) :: hands(1:max_hands)
|
||||
integer :: bids(1:max_hands)
|
||||
integer :: rank(1:max_hands)
|
||||
integer :: i, i2, n_hands
|
||||
integer :: istat
|
||||
integer :: beats, winnings, total_winnings
|
||||
|
||||
n_arguments = command_argument_count()
|
||||
if (n_arguments .eq. 1) then
|
||||
call get_command_argument(1, fname)
|
||||
print *, "File: ", trim(fname)
|
||||
print *
|
||||
else
|
||||
print *, "Wrong number of arguments: ", n_arguments
|
||||
stop
|
||||
end if
|
||||
|
||||
|
||||
open(10, file=fname)
|
||||
n_hands = 0
|
||||
do i=1, max_hands
|
||||
read(10, "(a)", iostat = istat) fline
|
||||
if ((len_trim(fline) .eq. 0) .or. (is_iostat_end(istat))) then
|
||||
exit
|
||||
end if
|
||||
read(fline, *) hands(i), bids(i)
|
||||
n_hands = n_hands + 1
|
||||
end do
|
||||
close(10)
|
||||
print *, "Number of hands: ", n_hands
|
||||
rank = -1
|
||||
rank(1) = 1
|
||||
print *
|
||||
do i=2,n_hands
|
||||
beats = 0
|
||||
do i2=1,(i-1)
|
||||
if (rank_correct(hands(i), hands(i2))) then
|
||||
! hand i ranks higher than hand i2
|
||||
if (rank(i2) .gt. beats) then
|
||||
beats = rank(i2)
|
||||
end if
|
||||
write(*, 21) i, hands(i), i2, hands(i2)
|
||||
else
|
||||
! hand i ranks lower than hand i2
|
||||
rank(i2) = rank(i2) + 1
|
||||
write(*, 22) i, hands(i), i2, hands(i2)
|
||||
end if
|
||||
end do
|
||||
rank(i) = beats+1
|
||||
end do
|
||||
print *
|
||||
total_winnings = 0
|
||||
do i=1, n_hands
|
||||
winnings = bids(i) * rank(i)
|
||||
write(*, 20) hands(i), bids(i), hand_type(hands(i)), rank(i), winnings
|
||||
total_winnings = total_winnings + winnings
|
||||
end do
|
||||
print *
|
||||
print *, "Total winnings: ", total_winnings
|
||||
|
||||
20 format("Hand: ", a5, "; Bid: ", i4, "; Type: ", i1, "; Rank: ", i4, "; Winnings: ", i8)
|
||||
21 format(i4, " (", a5, ") beats ", i4, " (", a5, ")")
|
||||
22 format(i4, " (", a5, ") b. by ", i4, " (", a5, ")")
|
||||
|
||||
contains
|
||||
function hand_type(hand)
|
||||
character(len=5), intent(in) :: hand
|
||||
integer :: hand_type
|
||||
character(len=1) :: dist_cards(1:5)
|
||||
integer :: card_count(1:5)
|
||||
integer :: n_dc
|
||||
integer :: i, i2
|
||||
character(len=1) :: this_card
|
||||
logical :: existing_card
|
||||
integer :: sets(1:5)
|
||||
integer :: n_jokers
|
||||
dist_cards = ' '
|
||||
card_count = 0
|
||||
n_dc = 1
|
||||
dist_cards(1) = hand(1:1)
|
||||
card_count(1) = 1
|
||||
do i=2,5
|
||||
this_card = hand(i:i)
|
||||
existing_card = .false.
|
||||
do i2=1,n_dc
|
||||
if (dist_cards(i2) .eq. this_card) then
|
||||
existing_card = .true.
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
if (existing_card) then
|
||||
card_count(i2) = card_count(i2) + 1
|
||||
else
|
||||
n_dc = n_dc + 1
|
||||
card_count(n_dc) = 1
|
||||
dist_cards(n_dc) = this_card
|
||||
end if
|
||||
end do
|
||||
sets = 0
|
||||
n_jokers = 0
|
||||
do i=1,n_dc
|
||||
if (dist_cards(i) .ne. 'J') then
|
||||
sets(card_count(i)) = sets(card_count(i)) + 1
|
||||
else
|
||||
n_jokers = card_count(i)
|
||||
end if
|
||||
end do
|
||||
if (n_jokers .eq. 5) then
|
||||
sets(5) = 1
|
||||
else if (n_jokers .gt. 0) then
|
||||
do i=4,1,-1
|
||||
if (sets(i) .gt. 0) then
|
||||
sets(i + n_jokers) = 1
|
||||
sets(i) = sets(i) - 1
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
end if
|
||||
if (sets(5) .eq. 1) then
|
||||
! Five of a kind
|
||||
hand_type = 7
|
||||
else if (sets(4) .eq. 1) then
|
||||
! Four of a kind
|
||||
hand_type = 6
|
||||
else if ((sets(3) .eq. 1) .and. (sets(2) .eq. 1)) then
|
||||
! Full house
|
||||
hand_type = 5
|
||||
else if (sets(3) .eq. 1) then
|
||||
! Three of a kind
|
||||
hand_type = 4
|
||||
else if (sets(2) .eq. 2) then
|
||||
! Two pair
|
||||
hand_type = 3
|
||||
else if (sets(2) .eq. 1) then
|
||||
! One pair
|
||||
hand_type = 2
|
||||
else
|
||||
! High card
|
||||
hand_type = 1
|
||||
end if
|
||||
end function hand_type
|
||||
|
||||
function tiebreak(hand1, hand2)
|
||||
! True if hand1 would tiebreak ahead of hand2
|
||||
implicit none
|
||||
character(len=5), intent(in) :: hand1, hand2
|
||||
logical :: tiebreak
|
||||
character(len=13) :: cards = "J23456789TQKA"
|
||||
integer :: pos_1, pos_2, i
|
||||
do i=1,5
|
||||
pos_1 = scan(cards, hand1(i:i))
|
||||
pos_2 = scan(cards, hand2(i:i))
|
||||
if (pos_1 .lt. pos_2) then
|
||||
tiebreak = .false.
|
||||
return
|
||||
else if (pos_1 .gt. pos_2) then
|
||||
tiebreak = .true.
|
||||
return
|
||||
end if
|
||||
end do
|
||||
tiebreak = .true.
|
||||
end function tiebreak
|
||||
|
||||
function rank_correct(hand1, hand2)
|
||||
implicit none
|
||||
character(len=5), intent(in) :: hand1, hand2
|
||||
logical :: rank_correct
|
||||
integer :: h1_type, h2_type
|
||||
h1_type = hand_type(hand1)
|
||||
h2_type = hand_type(hand2)
|
||||
if (h1_type .gt. h2_type) then
|
||||
rank_correct = .true.
|
||||
else if (h1_type .lt. h2_type) then
|
||||
rank_correct = .false.
|
||||
else
|
||||
rank_correct = tiebreak(hand1, hand2)
|
||||
end if
|
||||
end function rank_correct
|
||||
|
||||
|
||||
end program day7b
|
Loading…
Reference in New Issue