Games: Harry Poker solver
This is a solver for a game that I call "Harry Poker" (the name is not important, the full rules are not described here). This game is played with a normal deck of cards, 54 cards (4 suits of 13 cards each, plus 2 Jokers).
This is a maths game. Each card in the deck has a numerical value. The numbered cards have the value of the their face values. The other cards are: A = 1, J = 11, Q = 12, K = 13, Joker = 0.
The game is played between multiple players. The object of the game is get as close to a target value as possible. The player who gets closest to the target wins.
The target is a number. Each player gets a hand of three cards. Players must use five arithmetic operations: add, subtract, multiply, divide, and power, to combine the cards in their hand to get a number that is as close to the target as possible.
This script is a solver for this game. Given a target and a hand of cards, it will calculate "how close" that hand can get to the target. It does this by brute-forcing every possible combination of numbers and operations (except for the power operator).
$target = 72
$cards = @( 2, 3, 9 )
# use indices to refer to cards, in case two cards have the same value
$cardIndices = 0..2
$combos = Get-Combination $cardIndices 2
function sum([int]$a,[int]$b) {
Write-Host "$a + $b = $($a + $b)"
return $a + $b
}
function dif([int]$a,[int]$b) {
$big = if ($a -gt $b ) { $a } else { $b }
$small = if ($a -gt $b ) { $b } else { $a }
Write-Host "$big - $small = $($big - $small)"
# return [Math]::Abs($a - $b)
return $big - $small
}
function mul([int]$a,[int]$b) {
Write-Host "$a * $b = $($a * $b)"
return $a * $b
}
function div([int]$a,[int]$b) {
# only do divison that is greater than 0 (i.e. top number is bigger)
# and results in an integer
$big = if ($a -gt $b ) { $a } else { $b }
$small = if ($a -gt $b ) { $b } else { $a }
if ($small -eq 0) { return $null }
$div = $big / $small
if ([int] $div -eq $div) {
Write-Host "$big / $small = $($div)"
return $div
} else {
return $null
}
}
function pow([int]$a, [int]$b) {
if ($b -lt 0) { return $null } # negative exponent = fraction
$result = [Math]::Pow($a, $b)
if ($result -gt [int]::MaxValue) { return $null } # overflow
Write-Host "$a ^ $b = $($result)"
return [int]$result
}
function battery($pair) {
return @(
sum $pair[0] $pair[1]
dif $pair[0] $pair[1]
mul $pair[0] $pair[1]
div $pair[0] $pair[1]
pow $pair[0] $pair[1] # a^b
pow $pair[1] $pair[0] # b^a
)
}
$results = $combos |
% {
$pairIndices = @( $_.item1, $_.item2)
$pair = @(
$cards[$pairIndices[0]] # first number
$cards[$pairIndices[1]] # second number
)
[int] $thirdIndex = $cardIndices | ? { $_ -notin $pairIndices }
[int] $third = $cards[$thirdIndex] # third number
Write-Host "`nFirst pair: $pair" -ForegroundColor Yellow
$firstOp = battery $pair
Write-Host "`nSecond pair: $third" -ForegroundColor Yellow
$secondOp = $firstOp |
% {
if ($_ -ne $null) {
battery @(
[int] $_,
[int] $third
)
}
}
$away = $secondOp |
% {
write-host "$target - $_ = $([Math]::Abs($_ - $target))"
return [Math]::Abs($_ - $target)
}
$away
if ($away -eq 0) {
Write-Host "Exact match!" -ForegroundColor Green
break
}
}
$minimum = ($results | measure -Minimum).Minimum
Write-Host "The minimum is $minimum" -ForegroundColor Green