Construa trilhos de trem e engane o governo

30

Você é um empresário de ferrovias nos Estados Unidos do século XIX, quando os trens se tornam populares porque são os meios mais eficientes de transportar grandes volumes de materiais por terra. Existe uma necessidade nacional de trilhos de trem da costa leste através de algumas terras recentemente colonizadas no oeste.

Para acomodar essa necessidade, o governo dos EUA aplicará um imposto para subsidiar ferrovias. Eles prometeram pagar à sua empresa ferroviária por cada quilômetro percorrido. Como colocar trilhas em regiões montanhosas e montanhosas é mais caro do que colocar trilhas em terrenos planos, eles ajustam a quantia que dão em conformidade. Ou seja, o governo pagará

  • US $ 5.000 por milha de pista traçada em terreno plano
  • US $ 12.500 por milha de pista montada em terra montanhosa
  • US $ 20.000 por quilômetro de pista montada nas montanhas.

Obviamente, esse plano não reflete com precisão quanto custa realmente rastrear.

Você contratou alguns cartógrafos para desenhar mapas de relevo das regiões onde você seguirá o caminho para analisar a elevação. Aqui está um desses mapas:

S12321
121234
348E96

Cada dígito representa uma milha quadrada de terra. Sé o ponto de partida, Eé o ponto final. Cada número representa a intensidade das mudanças de altitude nessa região.

  • Terrenos numerados 1-3 constituem terreno plano.
  • Terrenos numerados 4-6 constituem terrenos montanhosos.
  • Os terrenos numerados 7-9 constituem uma cordilheira.

Através de anos de experiência na construção de trilhos de trem, avaliou que o custo de construção de trilhos (em dólares) satisfaz esta fórmula:

Cost_Per_Mile = 5000 + (1500 * (Elevation_Rating - 1))

Isso significa que a construção de certos gradientes de elevação custará mais dinheiro do que o governo concede, às vezes será rentável e, às vezes, você apenas empatará.

Por exemplo, uma milha de pista em um gradiente de elevação de 3 custa US $ 8.000 para construir, mas você recebe apenas US $ 5.000 por isso, e perde US $ 3.000. Por outro lado, construir uma milha de trilhos em um gradiente de elevação de 7 custa US $ 14.000, mas você recebe US $ 20.000 por isso: um lucro de US $ 6.000!

Aqui está um exemplo de mapa, bem como dois caminhos possíveis diferentes.

S29    S#9    S##
134    1#4    1##
28E    2#E    2#E

A primeira faixa custa US $ 30.000 para construir, mas o governo paga US $ 30.000 por ela. Você não lucra com esta faixa.

Por outro lado, o segundo custa 56.500 dólares para construir, mas você recebe 62.500 dólares por isso. Você lucra $ 6.000 com esta faixa.

Seu objetivo: com um mapa de relevo, encontre o caminho mais lucrativo (ou talvez apenas o menos caro) do início ao fim. Se vários caminhos estiverem vinculados, qualquer um deles é uma solução aceitável.

Detalhes do Programa

Você recebe uma entrada de texto separada por um mapa retangular de números e um ponto inicial e final. Cada número será um número inteiro, inclusive entre 1 e 9. Além disso, a entrada pode ser fornecida da maneira que você desejar, dentro do motivo.

A saída deve estar no mesmo formato da entrada, com os números nos quais a trilha foi construída substituída por um hash ( #). Por causa de regulamentações arbitrárias impostas por alguns políticos caprichosos, as trilhas só podem seguir caminhos horizontais ou verticais. Em outras palavras, você não pode voltar atrás ou seguir na diagonal.

O programa deve ser capaz de resolver em um período de tempo razoável (ou seja, <10 minutos) para mapas de até 6 linhas e 6 colunas.

Este é um desafio de código de golfe , portanto o programa mais curto vence.

Eu tenho uma implementação de exemplo (sem golfe) .

E / S de amostra

S12321
121234
348E96

S12321
######
3##E##



S73891
121234
348453
231654
97856E

S#3###
1###3#
3#####
######
#####E
Peter Olson
fonte
O que é, se a saída é ambígua?
FUZxxl
2
A saída pode ser ambígua, mas ambígua de uma maneira em que o lucro seja o mesmo, independentemente de como você o rastreie.
Peter Olson
Eu acho que há um pequeno erro. Deveria ser 4no 134mapa de exemplo 6?
JiminP
@JiminP Sim, isso foi um erro ao mudar os números em um lugar, mas não em outro. Deve ser corrigido agora.
Peter Olson
3
Três anos depois, o governo olha em volta e começa a se perguntar por que todas as colinas e montanhas estão cobertas por trilhos de trem. Mas, ei, os usuários locais de transporte público têm uma boa montanha-russa / passeio - de graça - financiado pelo governo, tornando as pessoas mais felizes, então por que se importar? (* Exceto para algumas colinas grau-6)
John Dvorak

Respostas:

5

Python, 307 caracteres

import os
I=os.read(0,99)
n=I.find('\n')+1
I='\0'*n+I+'\0'*n
def P(p):
 S=[]
 for d in(-n,-1,1,n):
  y=p[-1]+d
  if'E'==I[y]:S+=[(sum((int(I[v])-1)/3*75-15*int(I[v])+15for v in p[1:]),p)]
  if'0'<I[y]<':'and y not in p:S+=P(p+[y])
 return S
for i in max(P([I.find('S')]))[1][1:]:I=I[:i]+'#'+I[i+1:]
print I,

Ptoma um caminho parcial pe retorna todas as maneiras de estendê-lo para alcançá-lo E. Cada caminho retornado é emparelhado com sua pontuação para maxencontrar o melhor.

Leva cerca de 80 segundos em um mapa 6x6.

Keith Randall
fonte
11
Você pode substituir o segundo nível de recuos por tabulações para economizar 3 caracteres
gnibbler
4

Python: 529 482 460 bytes

Minha solução não ganhará nenhum prêmio. No entanto, como existem apenas duas soluções postadas e achei o problema interessante, decidi postar minha resposta de qualquer maneira.

Edit: Obrigado a Howard por suas recomendações. Consegui raspar muito da minha pontuação!

import sys
N=len
def S(m,c,p=0):
 if m[c]=='E':return m,p
 if m[c]<'S':
    b=list(m);b[c]='#';m=''.join(b)
 b=[],-float('inf')
 for z in(1,-1,w,-w):
    n=c+z
    if 0<=n<N(m)and m[n]not in('S','#')and(-2<z<2)^(n/w!=c/w):
     r=S(m,n,p+(0if m[n]=='E'else(int(m[n])-1)/3*5-int(m[n])+1))
     if b[1]<r[1]:b=r
 return b
m=''
while 1:
 l=sys.stdin.readline().strip()
 if l=='':break
 w=N(l);m+=l
b,_=S(m,m.index('S'))
for i in range(0,N(b),w):print b[i:i+w]
sadakatsu
fonte
É assim que começa. :)
Jonathan Van Matre
11
Algumas pequenas melhorias: Pe Msão usadas apenas uma vez cada uma, portanto, é uma boa ideia fazer a integração (para uma única invocação, funciona em quase todos os casos, para duas, às vezes). m[c]!='S'pode ser reduzido para m[c]<'S', também abs(z)==1para abs(z)<2ou mesmo -2<z<2.
Howard
Suas "pequenas melhorias" me salvam 47 bytes. Estou editando minha resposta.
Sadakatsu
3

Ruby, 233 caracteres

R=->s{o=s=~/S/m
s=~/E/m?(q=[-1,1,-N,N].map{|t|s[f=o+t]>'0'?(n=s*1
n[o]='#'
n[f]='S'
a=R[n]
a&&[a[0]-(e=s[f].to_i-1)/3*5+e,a[1]]):nil}-[nil]
q.sort!&&q[0]):[0,(n=s*1;n[o]='E'
n[$_=~/S/m]='S'
n)]}
N=1+(gets(nil)=~/$/)
$><<R[$_+$/*N][1]

Uma abordagem de força bruta Ruby que funciona bem dentro das restrições de tempo em uma placa 6x6. A entrada deve ser fornecida no STDIN.

Exemplos:

S12321
121234
348E96

S#2321
1#####
3##E##    
--    
S73891
121234
348453
231654
97856E

S#####
1212##
#####3
#3####
#####E
Howard
fonte
@PeterOlson Tentei dar pelo menos um pouco de atenção para o seu desafio ;-)
Howard