mirror of
https://github.com/Luzifer/codingame-solutions.git
synced 2024-12-22 18:51:20 +00:00
Initial commit of all the code
This commit is contained in:
commit
a675fdfabb
5 changed files with 567 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
current
|
349
finished/community_texas-holdem.go
Normal file
349
finished/community_texas-holdem.go
Normal file
|
@ -0,0 +1,349 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
WINNING_UNKNOWN uint = iota
|
||||
WINNING_HIGH_CARD
|
||||
WINNING_PAIR
|
||||
WINNING_TWO_PAIR
|
||||
WINNING_THREE_OF_A_KIND
|
||||
WINNING_STRAIGHT
|
||||
WINNING_FLUSH
|
||||
WINNING_FULL_HOUSE
|
||||
WINNING_FOUR_OF_A_KIND
|
||||
WINNING_STRAIGHT_FLUSH
|
||||
)
|
||||
|
||||
var (
|
||||
winningOutputs = map[uint]string{
|
||||
WINNING_HIGH_CARD: "HIGH_CARD",
|
||||
WINNING_PAIR: "PAIR",
|
||||
WINNING_TWO_PAIR: "TWO_PAIR",
|
||||
WINNING_THREE_OF_A_KIND: "THREE_OF_A_KIND",
|
||||
WINNING_STRAIGHT: "STRAIGHT",
|
||||
WINNING_FLUSH: "FLUSH",
|
||||
WINNING_FULL_HOUSE: "FULL_HOUSE",
|
||||
WINNING_FOUR_OF_A_KIND: "FOUR_OF_A_KIND",
|
||||
WINNING_STRAIGHT_FLUSH: "STRAIGHT_FLUSH",
|
||||
}
|
||||
handChecks = map[uint]handCheck{
|
||||
WINNING_HIGH_CARD: checkHighCard,
|
||||
WINNING_PAIR: checkPair,
|
||||
WINNING_TWO_PAIR: checkTwoPair,
|
||||
WINNING_THREE_OF_A_KIND: checkThreeOfAKind,
|
||||
WINNING_STRAIGHT: checkStraight,
|
||||
WINNING_FLUSH: checkFlush,
|
||||
WINNING_FULL_HOUSE: checkFullHouse,
|
||||
WINNING_FOUR_OF_A_KIND: checkFourOfAKind,
|
||||
WINNING_STRAIGHT_FLUSH: checkStraightFlush,
|
||||
}
|
||||
cardValues = map[byte]int{'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14}
|
||||
)
|
||||
|
||||
type card struct{ Value, Suit byte }
|
||||
type handCheck func(hand) (bool, string)
|
||||
type hand []card
|
||||
|
||||
func parseHand(player, board string) hand {
|
||||
all := strings.Split(player, " ")
|
||||
all = append(all, strings.Split(board, " ")...)
|
||||
|
||||
out := hand{}
|
||||
for i := 0; i < 7; i++ {
|
||||
out = append(out, card{all[i][0], all[i][1]})
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
type cardValueList []byte
|
||||
|
||||
func (c cardValueList) Len() int { return len(c) }
|
||||
func (c cardValueList) Less(i, j int) bool { return cardValues[c[i]] > cardValues[c[j]] }
|
||||
func (c cardValueList) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
|
||||
func main() {
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
scanner.Buffer(make([]byte, 1000000), 1000000)
|
||||
|
||||
scanner.Scan()
|
||||
holeCardsPlayer1 := scanner.Text()
|
||||
scanner.Scan()
|
||||
holeCardsPlayer2 := scanner.Text()
|
||||
scanner.Scan()
|
||||
communityCards := scanner.Text()
|
||||
|
||||
fmt.Fprintln(os.Stderr, "+-------- DBG -------+")
|
||||
fmt.Fprintf(os.Stderr, "| P1: %s |\n| P2: %s |\n| CO: %s |\n", holeCardsPlayer1, holeCardsPlayer2, communityCards)
|
||||
fmt.Fprintln(os.Stderr, "+-------- DBG -------+\n")
|
||||
|
||||
fmt.Println(executeChecks(holeCardsPlayer1, holeCardsPlayer2, communityCards))
|
||||
}
|
||||
|
||||
func executeChecks(holeCardsPlayer1, holeCardsPlayer2, communityCards string) string {
|
||||
player1Hand := parseHand(holeCardsPlayer1, communityCards)
|
||||
player2Hand := parseHand(holeCardsPlayer2, communityCards)
|
||||
|
||||
player1Result := WINNING_UNKNOWN
|
||||
player2Result := WINNING_UNKNOWN
|
||||
|
||||
var player1Out, player2Out string
|
||||
|
||||
for w, hc := range handChecks {
|
||||
if ok, out := hc(player1Hand); ok && w > player1Result {
|
||||
player1Result = w
|
||||
player1Out = out
|
||||
}
|
||||
|
||||
if ok, out := hc(player2Hand); ok && w > player2Result {
|
||||
player2Result = w
|
||||
player2Out = out
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case player1Result > player2Result:
|
||||
return fmt.Sprintf("1 %s %s", winningOutputs[player1Result], player1Out)
|
||||
case player2Result > player1Result:
|
||||
return fmt.Sprintf("2 %s %s", winningOutputs[player2Result], player2Out)
|
||||
case player2Result == player1Result:
|
||||
switch compareResultOutputHighCard(player1Out, player2Out) {
|
||||
case 1:
|
||||
return fmt.Sprintf("1 %s %s", winningOutputs[player1Result], player1Out)
|
||||
case 2:
|
||||
return fmt.Sprintf("2 %s %s", winningOutputs[player2Result], player2Out)
|
||||
}
|
||||
}
|
||||
|
||||
return "DRAW"
|
||||
}
|
||||
|
||||
func compareResultOutputHighCard(player1, player2 string) int {
|
||||
for i := 0; i < 5; i++ {
|
||||
switch {
|
||||
case cardValues[player1[i]] > cardValues[player2[i]]:
|
||||
return 1
|
||||
case cardValues[player1[i]] < cardValues[player2[i]]:
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h hand) OrderCards() []byte {
|
||||
cvs := []byte{}
|
||||
for _, c := range h {
|
||||
cvs = append(cvs, c.Value)
|
||||
}
|
||||
sort.Sort(cardValueList(cvs))
|
||||
return cvs
|
||||
}
|
||||
|
||||
func (h hand) CountValues() map[byte]int {
|
||||
out := map[byte]int{}
|
||||
|
||||
for _, c := range h {
|
||||
if _, ok := out[c.Value]; !ok {
|
||||
out[c.Value] = 0
|
||||
}
|
||||
out[c.Value]++
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (h hand) CountSuits() map[byte]int {
|
||||
out := map[byte]int{}
|
||||
|
||||
for _, c := range h {
|
||||
if _, ok := out[c.Suit]; !ok {
|
||||
out[c.Suit] = 0
|
||||
}
|
||||
out[c.Suit]++
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func cardOutput(cardValues []byte, winning []byte) string {
|
||||
kickers := []byte{}
|
||||
|
||||
for _, c := range cardValues {
|
||||
found := false
|
||||
for _, w := range winning {
|
||||
if w == c {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
kickers = append(kickers, c)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(cardValueList(kickers))
|
||||
|
||||
return strings.Join(cardValuesToList(winning...), "") + strings.Join(cardValuesToList(kickers[0:5-len(winning)]...), "")
|
||||
}
|
||||
|
||||
func cardValuesToList(vals ...byte) []string {
|
||||
out := []string{}
|
||||
for _, b := range vals {
|
||||
out = append(out, string(b))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func checkHighCard(cards hand) (bool, string) { return true, cardOutput(cards.OrderCards(), []byte{}) }
|
||||
|
||||
func checkPair(cards hand) (bool, string) {
|
||||
for val, count := range cards.CountValues() {
|
||||
if count == 2 {
|
||||
return true, cardOutput(cards.OrderCards(), []byte{val, val})
|
||||
}
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func checkTwoPair(cards hand) (bool, string) {
|
||||
var foundPairs = []byte{}
|
||||
|
||||
for val, count := range cards.CountValues() {
|
||||
if count == 2 {
|
||||
foundPairs = append(foundPairs, val)
|
||||
}
|
||||
}
|
||||
|
||||
if len(foundPairs) < 2 {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
sort.Sort(cardValueList(foundPairs))
|
||||
|
||||
pairs := []byte{foundPairs[0], foundPairs[0], foundPairs[1], foundPairs[1]}
|
||||
return true, cardOutput(cards.OrderCards(), pairs)
|
||||
|
||||
}
|
||||
|
||||
func checkThreeOfAKind(cards hand) (bool, string) {
|
||||
for val, count := range cards.CountValues() {
|
||||
if count == 3 {
|
||||
return true, cardOutput(cards.OrderCards(), []byte{val, val, val})
|
||||
}
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func checkStraight(cards hand) (bool, string) {
|
||||
order := cards.OrderCards()
|
||||
|
||||
if order[0] == 'A' { // Special case: Despite having value 14 an Ace can have value 1
|
||||
order = append(order, 'A')
|
||||
}
|
||||
|
||||
straightLength := 1
|
||||
for i := 1; i < len(order); i++ {
|
||||
if cardValues[order[i-1]] == cardValues[order[i]]+1 || (cardValues[order[i-1]] == 2 && order[i] == 'A') {
|
||||
straightLength++
|
||||
} else {
|
||||
straightLength = 1
|
||||
}
|
||||
|
||||
if straightLength == 5 {
|
||||
return true, cardOutput(cards.OrderCards(), order[i-4:i+1])
|
||||
}
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func checkFlush(cards hand) (bool, string) {
|
||||
var fiver byte
|
||||
|
||||
for suit, count := range cards.CountSuits() {
|
||||
if count >= 5 {
|
||||
fiver = suit
|
||||
}
|
||||
}
|
||||
|
||||
if fiver == 0x0 {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
matchedSuitValues := []byte{}
|
||||
for _, c := range cards {
|
||||
if c.Suit == fiver {
|
||||
matchedSuitValues = append(matchedSuitValues, c.Value)
|
||||
}
|
||||
}
|
||||
sort.Sort(cardValueList(matchedSuitValues))
|
||||
|
||||
return true, cardOutput(cards.OrderCards(), matchedSuitValues[0:5])
|
||||
}
|
||||
|
||||
func checkFullHouse(cards hand) (bool, string) {
|
||||
var (
|
||||
foundPairs = []byte{}
|
||||
foundThreeOfAKind = []byte{}
|
||||
)
|
||||
|
||||
for val, count := range cards.CountValues() {
|
||||
if count == 2 {
|
||||
foundPairs = append(foundPairs, val)
|
||||
} else if count == 3 {
|
||||
foundThreeOfAKind = append(foundThreeOfAKind, val)
|
||||
}
|
||||
}
|
||||
|
||||
if len(foundPairs) == 0 || len(foundThreeOfAKind) == 0 {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
sort.Sort(cardValueList(foundPairs))
|
||||
|
||||
winning := []byte{foundThreeOfAKind[0], foundThreeOfAKind[0], foundThreeOfAKind[0], foundPairs[0], foundPairs[0]}
|
||||
return true, cardOutput(cards.OrderCards(), winning)
|
||||
}
|
||||
|
||||
func checkFourOfAKind(cards hand) (bool, string) {
|
||||
for val, count := range cards.CountValues() {
|
||||
if count == 4 {
|
||||
return true, cardOutput(cards.OrderCards(), []byte{val, val, val, val})
|
||||
}
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func checkStraightFlush(cards hand) (bool, string) {
|
||||
var fiver byte
|
||||
|
||||
for suit, count := range cards.CountSuits() {
|
||||
if count >= 5 {
|
||||
fiver = suit
|
||||
}
|
||||
}
|
||||
|
||||
if fiver == 0x0 {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
matchedCards := hand{}
|
||||
for i := range cards {
|
||||
c := cards[i]
|
||||
if c.Suit == fiver {
|
||||
matchedCards = append(matchedCards, c)
|
||||
}
|
||||
}
|
||||
|
||||
return checkStraight(matchedCards)
|
||||
}
|
58
finished/medium_dont-panic-episode-1.go
Normal file
58
finished/medium_dont-panic-episode-1.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var (
|
||||
elevators = map[int]int{}
|
||||
blockersInPlace = map[int]bool{}
|
||||
)
|
||||
|
||||
func main() {
|
||||
// nbFloors: number of floors
|
||||
// width: width of the area
|
||||
// nbRounds: maximum number of rounds
|
||||
// exitFloor: floor on which the exit is found
|
||||
// exitPos: position of the exit on its floor
|
||||
// nbTotalClones: number of generated clones
|
||||
// nbAdditionalElevators: ignore (always zero)
|
||||
// nbElevators: number of elevators
|
||||
var nbFloors, width, nbRounds, exitFloor, exitPos, nbTotalClones, nbAdditionalElevators, nbElevators int
|
||||
fmt.Scan(&nbFloors, &width, &nbRounds, &exitFloor, &exitPos, &nbTotalClones, &nbAdditionalElevators, &nbElevators)
|
||||
|
||||
for i := 0; i < nbElevators; i++ {
|
||||
// elevatorFloor: floor on which this elevator is found
|
||||
// elevatorPos: position of the elevator on its floor
|
||||
var elevatorFloor, elevatorPos int
|
||||
fmt.Scan(&elevatorFloor, &elevatorPos)
|
||||
elevators[elevatorFloor] = elevatorPos
|
||||
}
|
||||
for {
|
||||
// cloneFloor: floor of the leading clone
|
||||
// clonePos: position of the leading clone on its floor
|
||||
// direction: direction of the leading clone: LEFT or RIGHT
|
||||
var cloneFloor, clonePos int
|
||||
var direction string
|
||||
fmt.Scan(&cloneFloor, &clonePos, &direction)
|
||||
|
||||
switch {
|
||||
case clonePos == 0 || clonePos == width-1:
|
||||
fmt.Println("BLOCK")
|
||||
blockersInPlace[cloneFloor] = true
|
||||
case direction == "RIGHT" && elevators[cloneFloor] < clonePos && !blockersInPlace[cloneFloor]:
|
||||
fmt.Println("BLOCK")
|
||||
blockersInPlace[cloneFloor] = true
|
||||
case direction == "LEFT" && elevators[cloneFloor] > clonePos && !blockersInPlace[cloneFloor]:
|
||||
fmt.Println("BLOCK")
|
||||
blockersInPlace[cloneFloor] = true
|
||||
case direction == "RIGHT" && exitPos < clonePos && exitFloor == cloneFloor && !blockersInPlace[cloneFloor]:
|
||||
fmt.Println("BLOCK")
|
||||
blockersInPlace[cloneFloor] = true
|
||||
case direction == "LEFT" && exitPos > clonePos && exitFloor == cloneFloor && !blockersInPlace[cloneFloor]:
|
||||
fmt.Println("BLOCK")
|
||||
blockersInPlace[cloneFloor] = true
|
||||
default:
|
||||
fmt.Println("WAIT")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
61
finished/medium_shadows-of-the-knight-episode-1.go
Normal file
61
finished/medium_shadows-of-the-knight-episode-1.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type bounds struct {
|
||||
X1, Y1, X2, Y2 int
|
||||
}
|
||||
|
||||
var (
|
||||
searchArea bounds
|
||||
myPosX, myPosY int
|
||||
)
|
||||
|
||||
func main() {
|
||||
// W: width of the building.
|
||||
// H: height of the building.
|
||||
var W, H int
|
||||
fmt.Scan(&W, &H)
|
||||
|
||||
searchArea = bounds{0, 0, W, H}
|
||||
|
||||
// N: maximum number of turns before game over.
|
||||
var N int
|
||||
fmt.Scan(&N)
|
||||
|
||||
fmt.Scan(&myPosX, &myPosY)
|
||||
|
||||
for {
|
||||
// bombDir: the direction of the bombs from batman's current location (U, UR, R, DR, D, DL, L or UL)
|
||||
var bombDir string
|
||||
fmt.Scan(&bombDir)
|
||||
|
||||
if strings.Contains(bombDir, "U") {
|
||||
searchArea.Y2 = myPosY
|
||||
}
|
||||
|
||||
if strings.Contains(bombDir, "D") {
|
||||
searchArea.Y1 = myPosY
|
||||
}
|
||||
|
||||
if strings.Contains(bombDir, "R") {
|
||||
searchArea.X1 = myPosX
|
||||
}
|
||||
|
||||
if strings.Contains(bombDir, "L") {
|
||||
searchArea.X2 = myPosX
|
||||
}
|
||||
|
||||
myPosX = searchArea.X1 + (searchArea.X2-searchArea.X1)/2
|
||||
myPosY = searchArea.Y1 + (searchArea.Y2-searchArea.Y1)/2
|
||||
|
||||
// the location of the next window Batman should jump to.
|
||||
fmt.Printf("%d %d\n",
|
||||
myPosX,
|
||||
myPosY,
|
||||
)
|
||||
}
|
||||
}
|
98
needs_improve/medium_mars-lander-episode-2.go
Normal file
98
needs_improve/medium_mars-lander-episode-2.go
Normal file
|
@ -0,0 +1,98 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
maxHorizontalSpeed = 30
|
||||
maxVerticalSpeed = 38
|
||||
maxRotation = 60
|
||||
)
|
||||
|
||||
var (
|
||||
maxTerrainHeight int
|
||||
startFlat, endFlat int
|
||||
flatHeight int
|
||||
)
|
||||
|
||||
func main() {
|
||||
// surfaceN: the number of points used to draw the surface of Mars.
|
||||
var surfaceN int
|
||||
fmt.Scan(&surfaceN)
|
||||
|
||||
lastTerrainY := math.MaxInt32
|
||||
var lastTerrainX int
|
||||
for i := 0; i < surfaceN; i++ {
|
||||
// landX: X coordinate of a surface point. (0 to 6999)
|
||||
// landY: Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars.
|
||||
var landX, landY int
|
||||
fmt.Scan(&landX, &landY)
|
||||
|
||||
if landY > maxTerrainHeight {
|
||||
maxTerrainHeight = landY
|
||||
}
|
||||
|
||||
if landY == lastTerrainY {
|
||||
startFlat = lastTerrainX
|
||||
endFlat = landX
|
||||
flatHeight = landY
|
||||
}
|
||||
|
||||
lastTerrainX = landX
|
||||
lastTerrainY = landY
|
||||
}
|
||||
|
||||
for {
|
||||
// hSpeed: the horizontal speed (in m/s), can be negative.
|
||||
// vSpeed: the vertical speed (in m/s), can be negative.
|
||||
// fuel: the quantity of remaining fuel in liters.
|
||||
// rotate: the rotation angle in degrees (-90 to 90).
|
||||
// power: the thrust power (0 to 4).
|
||||
var X, Y, hSpeed, vSpeed, fuel, rotate, power int
|
||||
fmt.Scan(&X, &Y, &hSpeed, &vSpeed, &fuel, &rotate, &power)
|
||||
|
||||
overFlatTerrain := X > startFlat && X < endFlat
|
||||
|
||||
rotation := 0
|
||||
power = 2
|
||||
desiredHorizontal := 0
|
||||
desiredVertical := -1 * maxVerticalSpeed
|
||||
|
||||
if X < startFlat {
|
||||
desiredHorizontal = maxHorizontalSpeed
|
||||
} else if X > endFlat {
|
||||
desiredHorizontal = -1 * maxHorizontalSpeed
|
||||
}
|
||||
|
||||
horizontalDelta := desiredHorizontal - hSpeed
|
||||
rotation = int(-1.0 * float64(maxRotation) * math.Min(1.0, (float64(horizontalDelta)/float64(maxHorizontalSpeed))))
|
||||
|
||||
if !overFlatTerrain {
|
||||
if Y < maxTerrainHeight+200 {
|
||||
desiredVertical = 5
|
||||
desiredHorizontal = 0
|
||||
} else {
|
||||
desiredVertical = -15
|
||||
}
|
||||
} else if math.Abs(float64(rotation)) > 0.0 {
|
||||
desiredVertical = -5
|
||||
}
|
||||
|
||||
if vSpeed < desiredVertical {
|
||||
power = 4
|
||||
rotationModifier := math.Max(0.4, 1.0/(float64(vSpeed)/float64(desiredVertical)))
|
||||
rotation = int(float64(rotation) * rotationModifier)
|
||||
}
|
||||
|
||||
if Y < flatHeight+50 {
|
||||
rotation = 0
|
||||
}
|
||||
|
||||
// fmt.Fprintln(os.Stderr, "Debug messages...")
|
||||
|
||||
// rotate power. rotate is the desired rotation angle. power is the desired thrust power.
|
||||
fmt.Printf("%d %d\n", rotation, power)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue