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

Add two new solutions

This commit is contained in:
Knut Ahlers 2016-10-14 20:57:32 +02:00
parent dd9a6c9db0
commit 1ea0dddd6d
Signed by: luzifer
GPG Key ID: DC2729FDD34BE99E
3 changed files with 314 additions and 0 deletions

View File

@ -9,5 +9,7 @@ Just one thing: **Don't just copy them.** Take the puzzle yourself and afterward
- Medium
- [Don't Panic - Episode 1](https://www.codingame.com/training/medium/don't-panic-episode-1)
- [Shadows of the Knight - Episode 1](https://www.codingame.com/training/medium/shadows-of-the-knight-episode-1)
- [Bender - Episode 1](https://www.codingame.com/training/medium/bender-episode-1)
- [There is no Spoon - Episode 1](https://www.codingame.com/training/medium/there-is-no-spoon-episode-1)
- Community
- [Texas Holdem](https://www.codingame.com/training/community/texas-holdem) by AdamHill

View File

@ -0,0 +1,201 @@
package main
import (
"bufio"
"errors"
"fmt"
"log"
"os"
"strings"
)
type direction string
const (
SOUTH direction = "SOUTH"
WEST = "WEST"
EAST = "EAST"
NORTH = "NORTH"
)
const (
MAP_TILE_OBSTACLE byte = 'X'
MAP_TILE_WALL = '#'
MAP_TILE_EAST = 'E'
MAP_TILE_WEST = 'W'
MAP_TILE_NORTH = 'N'
MAP_TILE_SOUTH = 'S'
MAP_TILE_BEER = 'B'
MAP_TILE_INVERT = 'I'
MAP_TILE_START = '@'
MAP_TILE_TELEPORTER = 'T'
MAP_TILE_FLOOR = ' '
MAP_TILE_DEATH = '$'
MAP_TILE_OUT_OF_BOUNDS = '?' // Internal error-reporter
)
var directionChange = map[bool][]direction{
false: []direction{SOUTH, EAST, NORTH, WEST},
true: []direction{WEST, NORTH, EAST, SOUTH},
}
type point struct{ X, Y int }
func (p point) Next(d direction) point {
switch d {
case SOUTH:
return point{p.X, p.Y + 1}
case WEST:
return point{p.X - 1, p.Y}
case NORTH:
return point{p.X, p.Y - 1}
case EAST:
return point{p.X + 1, p.Y}
}
return p
}
type playground struct {
Source string
Width, Height int
}
func (p playground) Get(pt point) byte {
pos := pt.Y*p.Width + pt.X
if pos >= len(p.Source) {
return MAP_TILE_OUT_OF_BOUNDS
}
return p.Source[pos]
}
func (p *playground) Set(pt point, mapReplace byte) {
pos := pt.Y*p.Width + pt.X
tmp := []byte(p.Source)
tmp[pos] = mapReplace
p.Source = string(tmp)
}
func (p playground) FindUniquePOI(poi byte) point {
pos := strings.IndexByte(p.Source, poi)
return point{X: pos % p.Width, Y: pos / p.Width}
}
func (p playground) FindMultiplePOI(poi byte) []point {
out := []point{}
for pos := 0; pos < len(p.Source); pos++ {
if p.Source[pos] == poi {
out = append(out, point{X: pos % p.Width, Y: pos / p.Width})
}
}
return out
}
type bender struct {
City playground
Position point
BeerMode bool
InvertMode bool
MoveDirection direction
path []string
}
func (b *bender) Init() {
b.Position = b.City.FindUniquePOI(MAP_TILE_START)
b.MoveDirection = SOUTH
}
func (b bender) Path() string {
return strings.Join(b.path, "\n")
}
func (b *bender) Trace(maxSteps int) error {
madeSteps := 0
for madeSteps < maxSteps {
nextPos := b.Position.Next(b.MoveDirection)
nd := 0
for b.City.Get(nextPos) == MAP_TILE_OBSTACLE || b.City.Get(nextPos) == MAP_TILE_WALL {
if b.BeerMode && b.City.Get(nextPos) == MAP_TILE_OBSTACLE {
b.City.Set(nextPos, MAP_TILE_FLOOR)
} else {
b.MoveDirection = directionChange[b.InvertMode][nd]
nextPos = b.Position.Next(b.MoveDirection)
nd++
}
}
b.Position = nextPos
log.Printf("Moved to %#v", b.Position)
b.path = append(b.path, string(b.MoveDirection))
switch b.City.Get(b.Position) {
case MAP_TILE_START:
return errors.New("Returned to start, no cool.")
case MAP_TILE_OUT_OF_BOUNDS:
return errors.New("Bender left the map. How?!?")
case MAP_TILE_WEST:
b.MoveDirection = WEST
case MAP_TILE_EAST:
b.MoveDirection = EAST
case MAP_TILE_SOUTH:
b.MoveDirection = SOUTH
case MAP_TILE_NORTH:
b.MoveDirection = NORTH
case MAP_TILE_BEER:
b.BeerMode = !b.BeerMode
case MAP_TILE_INVERT:
b.InvertMode = !b.InvertMode
case MAP_TILE_DEATH:
// We got killed. Bye cruel world!
return nil
case MAP_TILE_TELEPORTER:
teleporters := b.City.FindMultiplePOI(MAP_TILE_TELEPORTER)
for i := range teleporters {
t := teleporters[i]
if t.X == b.Position.X && t.Y == b.Position.Y {
continue
}
b.Position = t
log.Printf("Bzzzzp. Now at: %#v", b.Position)
break
}
}
madeSteps++
}
return errors.New("Max steps reached. (LOOP)")
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
var L, C int
scanner.Scan()
fmt.Sscan(scanner.Text(), &L, &C)
b := &bender{}
b.City.Width = C
b.City.Height = L
for i := 0; i < L; i++ {
scanner.Scan()
b.City.Source = b.City.Source + scanner.Text()
}
b.Init()
log.Printf("%#v", b)
if err := b.Trace(L * C); err != nil {
log.Printf("Trace error: %s", err)
fmt.Println("LOOP")
} else {
fmt.Println(b.Path())
}
}

View File

@ -0,0 +1,111 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"sync"
)
const (
CHAR_NODE = '0'
CHAR_FREE = '.'
)
type playground struct {
Source string
Width, Height int
}
func (p playground) Scan() <-chan string {
log.Printf("%#v", p)
c := make(chan string, 100)
go func() {
defer close(c)
wg := sync.WaitGroup{}
for i := 0; i < len(p.Source); i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
x := i % p.Width
y := i / p.Width
if p.get(x, y) != CHAR_NODE {
return
}
log.Printf("X: %d Y: %d", x, y)
c <- p.GetNeighborNotation(x, y)
}(i)
}
wg.Wait()
}()
return c
}
func (p playground) get(x, y int) byte {
pos := y*p.Width + x
log.Printf("Getting x=%d y=%d (str=%d, char=%c", x, y, pos, p.Source[pos])
if pos >= len(p.Source) {
return '?'
}
return p.Source[pos]
}
func (p playground) GetNeighborNotation(x, y int) string {
bx, by := p.getBottomNext(x, y+1)
rx, ry := p.getRightNext(x+1, y)
return fmt.Sprintf("%d %d %d %d %d %d", x, y, rx, ry, bx, by)
}
func (p playground) getBottomNext(x, y int) (int, int) {
if y >= p.Height {
return -1, -1
}
if p.get(x, y) == CHAR_NODE {
return x, y
}
return p.getBottomNext(x, y+1)
}
func (p playground) getRightNext(x, y int) (int, int) {
if x >= p.Width {
return -1, -1
}
if p.get(x, y) == CHAR_NODE {
return x, y
}
return p.getRightNext(x+1, y)
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
// width: the number of cells on the X axis
var width int
scanner.Scan()
fmt.Sscan(scanner.Text(), &width)
// height: the number of cells on the Y axis
var height int
scanner.Scan()
fmt.Sscan(scanner.Text(), &height)
pg := playground{Width: width, Height: height}
for i := 0; i < height; i++ {
scanner.Scan()
pg.Source = pg.Source + scanner.Text()
}
for out := range pg.Scan() {
fmt.Println(out)
}
}