O problema do peão perdido

14

O problema do peão perdido

Depois que o jogo terminou, um peão sobrevivente foi deixado para trás das linhas inimigas. vamos ajudá-lo a encontrar o caminho mais curto para voltar para casa.

O problema original descreve um tabuleiro de xadrez nXn e uma função f: {1,..,n-1}X{1,..,n}X{-1,0,1} => R+de pesos. o objetivo é encontrar o melhor caminho de algum quadrado na linha inferior, para outro quadrado na linha superior, onde os movimentos possíveis são: esquerda para cima, para cima, para a direita e você não pode sair do tabuleiro.

O problema é relativamente fácil de resolver em O (n ^ 2) usando programação dinâmica, mas isso é codegolf, e não nos importamos com coisas inúteis, como complexidade do tempo de execução ...

O problema

input: uma matriz tridimensional (ou alguma outra coleção de sua escolha, recebida através de stdin ou como argumento de função), correspondente a um tabuleiro de xadrez regular, exatamente no tamanho: 7X8X3 (#linePasses X #rowSize X #movesPerPass) contendo números inteiros não negativos. os movimentos custam de alguma posição em (i,j)que iestá o índice de linha e jo índice de coluna são:

  • a[i][j][0]para o custo de viajar up-esquerda para a praça (i+1,j-1), ou graficamente: \.
  • a[i][j][1]para o custo de viajar até ao quadrado (i+1,j), ou graficamente: |.
  • a[i][j][2]para o custo de viajar até direito ao quadrado (i+1,j+1), ou graficamente: /.

você pode presumir que não conterá um caminho que tenha somas maiores que MAX_INT.

saída: uma saída 8X8 ascii mostrando o melhor caminho (menor, ou seja, a soma mínima de pesos) (se houver mais de um resultado ideal, você poderá mostrar um caminho arbitrário de sua escolha). o caminho é desenhado de baixo para cima, onde em cada linha, o caractere correspondente à posição do peão no caminho, é o que ele está prestes a criar. por exemplo, se o peão estiver prestes a se mover para cima-esquerda da coluna 3 (para a coluna 2), você deve desenhar:

#?######
##\#####

onde ?deve ser substituído pelo próximo passo. posição final precisa ser desenhada como X.

Exemplos

entrada:

[
  [[1,1,1],[1,1,1],[0,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,0,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,0],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,0],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,1],[1,0,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,1],[1,0,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,1],[0,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]]
]

resultado:

##X#####
###\####
###|####
###|####
##/#####
#/######
#|######
##\#####

entrada:

[
  [[41,27,38],[12,83,32],[50,53,35],[46,32,26],[55,89,82],[75,30,87],[2,11,64],[8,55,22]],
  [[56,21,0],[83,25,38],[43,75,63],[56,60,77],[68,55,89],[99,48,67],[94,30,9],[62,62,58]],
  [[23,18,40],[24,47,61],[96,45,72],[71,6,48],[75,63,98],[93,56,51],[23,31,30],[49,34,99]],
  [[20,47,42],[62,79,72],[32,28,44],[68,61,55],[62,39,57],[4,17,49],[97,85,6],[91,18,12]],
  [[51,50,11],[32,39,56],[12,82,23],[33,88,87],[60,55,22],[29,78,14],[70,11,42],[63,94,67]],
  [[75,64,60],[27,79,86],[70,72,56],[55,45,32],[95,67,12],[87,93,98],[81,36,53],[38,22,93]],
  [[31,80,50],[77,71,22],[59,46,86],[64,71,53],[41,19,95],[62,71,22],[92,80,41],[26,74,29]]
]

resultado:

######X#
#####/##
####/###
#####\##
#####|##
######\#
######|#
#######\

isso é , então o código mais curto vence.

jogue Limpo. sem brechas ...

EDITAR:

Iv'e escreveu uma solução direta e não-golfe em scala que você pode olhar. Há também um site que você pode jogar com o código scala on-line: scalakata (basta copiar e colar a essência do scalakata e pressionar o botão play)

Gilad Hoch
fonte

Respostas:

5

Q: 199 bytes

f:{m::x;n::{@/[+/-1 0 1_\:/:(x;m[y;;|!3]);0 2;(0W,),{x,0W}]};i:*<*|r:{&/n[x;y]}\[8#0;!7];  s:{-1+{*<x}'+n[y;z]}\[();(,8#0),-1_r;!7];j:i,{x+y x}\[i;|s];-1(@[8#"#";;:;]'[j;"X","/|\\"1+s'[|!7;-1_j]]);}

NOTAS

  • Intérprete Q (kx.com) grátis para uso não comercial (versões para Windows, Linux, Mac)
  • Esta solução usa o núcleo interno de Q (denominado internamente k4), portanto, precisamos de um arquivo de script com extensão k ou intérprete interativo no modo k (\ comando no primeiro prompt). Por outro lado, a versão 'detalhada' (legível) da linguagem requer um script com extensão q e é o modo padrão no intérprete interativo.

TESTE

f ((1 1 1; 1 1 1; 0 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 0 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 0; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 0; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 1; 1 0 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 1; 1 0 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 1; 0 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1))

##X#####
###\####
###|####
###|####
##/#####
#/######
#|######
##\#####

f ((41 27 38; 12 83 32; 50 53 35; 46 32 26; 55 89 82; 75 30 87;  2 11 64;  8 55 22)
   (56 21  0; 83 25 38; 43 75 63; 56 60 77; 68 55 89; 99 48 67; 94 30  9; 62 62 58)
   (23 18 40; 24 47 61; 96 45 72; 71  6 48; 75 63 98; 93 56 51; 23 31 30; 49 34 99)
   (20 47 42; 62 79 72; 32 28 44; 68 61 55; 62 39 57;  4 17 49; 97 85  6; 91 18 12)
   (51 50 11; 32 39 56; 12 82 23; 33 88 87; 60 55 22; 29 78 14; 70 11 42; 63 94 67)
   (75 64 60; 27 79 86; 70 72 56; 55 45 32; 95 67 12; 87 93 98; 81 36 53; 38 22 93)
   (31 80 50; 77 71 22; 59 46 86; 64 71 53; 41 19 95; 62 71 22; 92 80 41; 26 74 29))

######X#
#####/##
####/###
#####\##
######\#
######|#
######|#
#######\

EXPLICAÇÃO

Para fins de ilustração, assumimos o segundo teste (matriz ((41 27 38; 12 83 32; ....)

Transformamos a matriz original (m no nível do código): em vez da matriz orginimal com um trigêmeo para cada coordenada, definimos a matriz para os deslocamentos esquerdo, para cima e para a direita. A matriz esquerda contém valores 7x7 (deixamos cair a primeira coluna), a matriz Up 7x8 e a matriz direita 7x7 (deixamos a última coluna).

left                           up                         right
12 50 46 55 75 2  8       27 83 53 32 89 30 11 55     38 32 35 26 82 87 64
83 43 56 68 99 94 62      21 25 75 60 55 48 30 62     0  38 63 77 89 67 9 
24 96 71 75 93 23 49      18 47 45 6  63 56 31 34     40 61 72 48 98 51 30
62 32 68 62 4  97 91      47 79 28 61 39 17 85 18     42 72 44 55 57 49 6 
32 12 33 60 29 70 63      50 39 82 88 55 78 11 94     11 56 23 87 22 14 42
27 70 55 95 87 81 38      64 79 72 45 67 93 36 22     60 86 56 32 12 98 53
77 59 64 41 62 92 26      80 71 46 71 19 71 80 74     50 22 86 53 95 22 41

Para calcular a posição final, precisamos avaliar o caminho do custo mínimo. Assumimos o custo inicial 0 0 0 0 0 0 0 0 (custo para chegar a cada coluna da primeira linha) e itera a cada linha seguinte. Em cada coluna i, calculamos três valores:

  • custo do valor i + 1 anterior mais a esquerda [i + 1]. Largamos o primeiro componente do custo (turnos e alinea colunas a serem adicionadas) e somamos o componente ao componente

  • custo do valor anterior de i mais [i]. Somamos componente a componente

  • custo do valor i-1 anterior mais o direito [i-1]. Soltamos o último componente do custo (turnos e colunas alineadas a serem adicionadas) e somamos o componente ao componente

Para calcular o mínimo, concluímos o custo esquerdo acrescentando infinito e o custo direito acrescentando infinito: com 3 vetores de oito componentes, calcule o componente mínimo a componente. O valor resultante é o custo base para nova iteração

Para a primeira iteração, obtemos valores (0W é infinito em Q)

0W 12 50 46 55 75 2  8
27 83 53 32 89 30 11 55
38 32 35 26 82 87 64 0W

e calcula o mínimo de cada coluna

27 12 35 26 55 30 2 8

Depois de todas as iterações, temos o custo mínimo para chegar a cada quadrado (assumindo a linha 0 na parte superior, 7 na parte inferior). Estamos interessados ​​apenas na última coluna, mas desenho todos os resultados intermediários para fins ilustrativos

0   0   0   0   0   0   0   0
27  12  35  26  55  30  2   8
27  37  78  82  110 78  11  70
45  61  123 88  173 129 34  104
87  123 151 143 212 133 40  122
98  155 163 176 234 147 51  185
158 182 219 208 246 234 87  207
208 204 265 261 265 256 128 233

Agora encontramos o valor mínimo na última linha (128, na coluna 6). Esse é o fim do caminho (caractere X na saída).

Repetimos o cálculo de custo novamente, mas agora anotamos a direção em que obtemos cada mínimo (qual dos 3 valores usados ​​para calcular o mínimo é o valor selecionado).

\|/|\///
\\\\\/|/
\\\|//|/
\\|\//|/
\\|//|\/
\\//|\|/
\|/|/|\/

Invertemos as linhas, colocamos 'X' na posição 6 e preservamos apenas o caminho que termina na coluna 6 (os outros são substituídos por #)

######X#
#####/##
####/###
#####\##
######\#
######|#
######|#
#######\
J. Sendra
fonte
Iv'e nunca ouvi falar de Q, mas obrigado por uma resposta tão detalhadas :)
gilad hoch