1
0
mirror of https://github.com/Luzifer/codingame-solutions.git synced 2024-09-16 14:18:33 +00:00

Initial commit of all the code

This commit is contained in:
Knut Ahlers 2016-10-14 17:27:23 +02:00
commit a675fdfabb
Signed by: luzifer
GPG Key ID: DC2729FDD34BE99E
5 changed files with 567 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
current

View 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)
}

View 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")
}
}
}

View 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,
)
}
}

View 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)
}
}