Costruisci i binari della ferrovia e imbroglia il governo


30

Sei un imprenditore delle ferrovie negli Stati Uniti del XIX secolo quando i treni diventano popolari perché sono il mezzo più efficiente per trasportare grandi volumi di materiali via terra. C'è un bisogno nazionale di binari ferroviari dalla costa orientale attraverso alcune terre recentemente colonizzate a ovest.

Per soddisfare questa esigenza, il governo degli Stati Uniti imporrà un'imposta per sovvenzionare le ferrovie. Hanno promesso di pagare soldi alla compagnia ferroviaria per ogni miglio di binario tracciato. Poiché la posa dei binari nelle regioni collinari e montane è più costosa rispetto alla posa dei binari in pianura, essi adeguano di conseguenza l'importo che danno. Cioè, il governo pagherà

  • $ 5.000 per miglio di binario posato in terra piatta
  • $ 12.500 per miglio di binario posato in terra collinare
  • $ 20.000 per miglio di binario posato in montagna.

Naturalmente, questo piano non riflette accuratamente quanto effettivamente costa tracciare le tracce.

Hai assunto alcuni cartografi per disegnare mappe in rilievo delle regioni in cui dovrai tracciare la traccia per analizzare l'elevazione. Ecco una di queste mappe:

S12321
121234
348E96

Ogni cifra rappresenta un miglio quadrato di terra. Sè il punto iniziale, Eè il punto finale. Ogni numero rappresenta l'intensità delle variazioni di elevazione in quella regione.

  • Il terreno numerato 1-3 costituisce un terreno pianeggiante.
  • La terra numerata 4-6 costituisce terra collinare.
  • La terra numerata 7-9 costituisce una catena montuosa.

Attraverso anni di esperienza nella costruzione di binari ferroviari, hai valutato che il costo di costruzione di binari (in dollari) soddisfa questa formula:

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

Ciò significa che basarsi su determinati gradienti di elevazione ti costerà più denaro di quello che il governo offre, a volte sarà redditizio, a volte anche solo in pareggio.

Ad esempio, un miglio di pista su un gradiente di elevazione di 3 costa $ 8.000 per la costruzione, ma ricevi solo $ 5.000 per questo, quindi perdi $ 3000. Al contrario, costruire un miglio di pista su un dislivello di 7 costa $ 14.000, ma vieni pagato $ 20.000: un profitto di $ 6.000!

Ecco una mappa di esempio, oltre a due diversi percorsi possibili.

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

La prima traccia costa $ 30.000 dollari per essere costruita, ma il governo ti paga $ 30.000 per questo. Non trarre profitto da questa traccia.

D'altra parte, il secondo costa $ 56.500 per la costruzione, ma vieni pagato $ 62.500 per questo. Guadagni $ 6.000 da questa traccia.

Il tuo obiettivo: data una mappa di rilievo, trova il percorso più redditizio (o forse solo il meno costoso) dall'inizio alla fine. Se più percorsi si legano, ognuno di essi è una soluzione accettabile.

Dettagli del programma

Viene fornito un input di testo separato con una mappa rettangolare di numeri e un punto iniziale e finale. Ogni numero sarà un numero intero compreso tra 1 e 9. A parte questo, l'ingresso può essere fornito come preferisci, entro limiti ragionevoli.

L'output dovrebbe essere nello stesso formato dell'input, con i numeri in cui la traccia è stata costruita sostituita da un hash ( #). A causa delle normative arbitrarie imposte da alcuni politici capricciosi, le tracce possono andare solo su percorsi orizzontali o verticali. In altre parole, non puoi tornare indietro o andare in diagonale.

Il programma dovrebbe essere in grado di risolvere in un ragionevole lasso di tempo (cioè <10 minuti) per mappe fino a 6 righe e 6 colonne.

Questa è una sfida del codice golf , quindi vince il programma più breve.

Ho un'implementazione di esempio (non golfizzata) .

I / O di esempio

S12321
121234
348E96

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



S73891
121234
348453
231654
97856E

S#3###
1###3#
3#####
######
#####E

Cos'è, se l'output è ambiguo?
FUZxxl,

2
L'output può essere ambiguo, ma ambiguo in un modo in cui il profitto è lo stesso indipendentemente da come lo si traccia.
Peter Olson,

Penso che ci sia un piccolo errore. Dovrebbe 4in 134nell'esempio mappa essere 6?
JiminP

@JiminP Sì, è stato un errore cambiare i numeri in un posto ma non in un altro. Ora dovrebbe essere risolto.
Peter Olson,

3
Tre anni dopo, il governo si guarda intorno e inizia a chiedersi perché tutte * le colline e le montagne siano coperte dai binari della ferrovia. Ma hey, gli utenti del trasporto pubblico locale hanno ottenuto un bel giro sulle montagne russe / giro turistico --- gratuitamente --- finanziato dal governo, rendendo le persone più felici, quindi perché preoccuparsene? (* tranne che per alcune colline di livello 6)
John Dvorak,

Risposte:


5

Python, 307 caratteri

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,

Pprende un percorso parziale pe restituisce tutti i modi di estenderlo per raggiungere E. Ogni percorso restituito è accoppiato con il suo punteggio in modo da maxpoter trovare quello migliore.

Dura circa 80 secondi su una mappa 6x6.


1
È possibile sostituire il secondo livello di rientri con le schede per salvare 3 caratteri
gnibbler

4

Python: 529 482 460 byte

La mia soluzione non vincerà alcun premio. Tuttavia, poiché sono state pubblicate solo due soluzioni e ho riscontrato il problema interessante, ho deciso di pubblicare comunque la mia risposta.

Modifica: grazie a Howard per i suoi consigli. Sono riuscito a radere molto del mio punteggio!

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]

È così che inizia. :)
Jonathan Van Matre

1
Alcuni piccoli miglioramenti: Pe Msono usati solo una volta ciascuno, quindi è una buona idea incorporare poi (per una singola invocazione funziona in quasi tutti i casi per due a volte). m[c]!='S'può essere accorciato per m[c]<'S', anche abs(z)==1a abs(z)<2o addirittura -2<z<2.
Howard,

I tuoi "miglioramenti minori" mi fanno risparmiare 47 byte. Sto modificando la mia risposta.
Sadakatsu,

3

Rubino, 233 caratteri

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]

Un approccio alla forza bruta di Ruby che funziona bene entro i limiti di tempo su una scheda 6x6. L'ingresso deve essere dato su STDIN.

Esempi:

S12321
121234
348E96

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

S#####
1212##
#####3
#3####
#####E

@PeterOlson Ho provato a prestare almeno un po 'di attenzione alla tua sfida ;-)
Howard
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.