commit a675fdfabba1a226e062bddbf5aaf488f8696e49 Author: Knut Ahlers Date: Fri Oct 14 17:27:23 2016 +0200 Initial commit of all the code diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b9023a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +current diff --git a/finished/community_texas-holdem.go b/finished/community_texas-holdem.go new file mode 100644 index 0000000..abaaa39 --- /dev/null +++ b/finished/community_texas-holdem.go @@ -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) +} diff --git a/finished/medium_dont-panic-episode-1.go b/finished/medium_dont-panic-episode-1.go new file mode 100644 index 0000000..9c770eb --- /dev/null +++ b/finished/medium_dont-panic-episode-1.go @@ -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") + } + + } +} diff --git a/finished/medium_shadows-of-the-knight-episode-1.go b/finished/medium_shadows-of-the-knight-episode-1.go new file mode 100644 index 0000000..58bfdb5 --- /dev/null +++ b/finished/medium_shadows-of-the-knight-episode-1.go @@ -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, + ) + } +} diff --git a/needs_improve/medium_mars-lander-episode-2.go b/needs_improve/medium_mars-lander-episode-2.go new file mode 100644 index 0000000..71db9c7 --- /dev/null +++ b/needs_improve/medium_mars-lander-episode-2.go @@ -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) + } +}