Scegli la tua avventura


17

Scegli i tuoi libri di avventura sono una forma di letteratura interattiva in cui il lettore deve prendere decisioni che influenzano il risultato della storia. In alcuni punti della storia, il lettore ha più opzioni che possono essere scelte, ognuna delle quali invia il lettore a una pagina diversa del libro.

Ad esempio, in un ambiente fantasy, potrebbe essere necessario decidere a pagina 14 se avventurarsi in una caverna misteriosa "saltando" a pagina 22 o esplorare la foresta vicina saltando a pagina 8. Questi "salti" possono essere espressi come coppie di numeri di pagina, in questo modo:

14 22
14 8

Nella maggior parte dei casi, ci sono molti finali della storia, ma solo alcuni buoni. L'obiettivo è quello di navigare nella storia per raggiungere un buon finale.

Compito:

Dato un elenco di "salti" per un determinato libro, il tuo compito è determinare un percorso che porterà a un finale specifico. Poiché questo è abbastanza facile, la vera sfida è farlo nel minor numero di personaggi possibile.

Questo è il codice golf .

Input di esempio (dove 1 è l'inizio e 100 è l'obiettivo):

1 10
10 5
10 13
5 12
5 19
13 15
12 20
15 100

Uscita campione:

1 10 13 15 100

Input di esempio:

15 2
1 4
2 12
1 9
3 1
1 15
9 3
12 64
4 10
2 6
80 100
5 10
6 24
12 80
6 150
120 9
150 120

Uscita campione:

1 15 2 12 80 100

Appunti:

  • L'elenco dei salti verrà inserito dall'utente, da un file o da uno stdin. Puoi scegliere quello che è più conveniente.
  • L'ingresso conterrà 1 salto per riga, con l'origine e la destinazione separate da un singolo spazio.
  • Le linee nell'input non sono garantite in un ordine specifico.
  • Un percorso riuscito inizierà a pagina 1 e terminerà a pagina 100.
  • Puoi presumere che ci sia almeno 1 percorso verso l'obiettivo. Non è necessario trovare tutti i percorsi, né è necessario trovare il più breve. Basta trovarne almeno uno.
  • Il numero di pagina più piccolo sarà 1. Non c'è limite al numero di pagina più grande. (Puoi presumere che si adatterà nell'intervallo di un int.)
  • Possono esistere dei loop. Ad esempio, l'elenco può avere salti da pagina 5 a 10, da 10 a 19 e da 19 a 5.
  • Potrebbero esserci dei vicoli ciechi. Cioè, una pagina di destinazione potrebbe non avere un posto in cui saltare.
  • Al contrario, potrebbero esserci pagine irraggiungibili. Cioè, una pagina di origine potrebbe non essere la destinazione di alcun salto.
  • Non tutti i numeri di pagina compresi tra 1 e 100 sono garantiti per l'uso.
  • L'output deve essere costituito da un percorso valido di numeri di pagina, che iniziano con 1 e terminano con 100, separati da spazi.

Ricorda, questo è il golf del codice, quindi vince la soluzione più breve!

EDIT: aggiunto un altro campione per il test.


1
Possiamo supporre che non ci siano salti da pagina 100?
Peter Taylor,

Sì, puoi supporre che.
migimaru,

ho la sensazione che qualcosa come lisp o lega possa farlo in pochissimi caratteri, ci proverò più tardi quando esco dal lavoro.
JoséNunoFerreira,

Risposte:


7

Golfscript, 58 57 caratteri

~]2/.,{:A{){=}+{0=}\+A\,\`{\+}+/}/]A+}*{)100=\0=1=*}?' '*

Attenzione : questo è super-inefficiente. Funziona quadrando ripetutamente la matrice di adiacenza e quindi cercando una rotta; se ci sono Ebordi nel grafico, troverà ogni percorso di lunghezza fino a 2 E (e quelli più corti troverà molte volte). Dovrebbe darti un risultato per il primo caso di test in un tempo ragionevole, ma se vuoi provare il secondo assicurati di avere qualche concerto libero di memoria e fai una lunga passeggiata.

Se desideri una soluzione ragionevolmente efficiente, offro a 67 caratteri:

~]2/:A,[1]]({A{{{?)}+1$\,,}%~!*},{({\-1==}+2$?\[+]+}/}*{100?)}?' '*

Non mi ero reso conto che potevi fare la moltiplicazione di matrici in Golfscript!
migimaru,

@migimaru, è un linguaggio potente di Turing, per quanto molte lacune possano avere la sua gestione dell'array.
Peter Taylor,

È vero. Immagino che non mi aspettassi di vedere le matrici di adiacenza adattarsi in uno spazio così piccolo;)
migimaru,

@Peter Siamo spiacenti, ho provato a farlo funzionare cat input | ruby1.9 golfscript.rb peter.gse tutto ciò che è accaduto è stato che il mio MacBook è diventato davvero caldo. Come dovrei eseguirlo?
Gareth,

3
@Gareth, sì. Quando l'ho ucciso dopo mezz'ora, era fino a 2 GB di memoria. Renderò l'avvertimento un po 'più esplicito.
Peter Taylor,

14

Python, 232 213 157 143 135 132 caratteri (percorso più breve)

Questa implementazione può gestire tutti i casi limite descritti (loop, vicoli ciechi, pagine orfane ecc.) E garantisce che troverà il percorso più breve verso il finale. Si basa sull'algoritmo del percorso più breve di Djikstra.

import sys
l=[k.split()for k in sys.stdin]
s={"100":"100"}
while"1"not in s:
 for i,j in l:
    if j in s:s[i]=i+" "+s[j]
print s["1"]

3

Javascript: 189 personaggi

Questa è una soluzione ricorsiva che trova il percorso più breve attraverso l'avventura.

Codice-golfed:

a=prompt().split('\\n');b=0;while(!(d=c(b++,1)));function c(e,f,i,g){if(e>0)for(i=0;h=a[i++];){g=h.split(' ');if(g[0]==f){if(g[1]==100)return h;if(j=c(e-1,g[1]))return g[0]+' '+j}}}alert(d)

Per testare ( ATTENZIONE: loop infinito per input errato! ):

  1. Copia una delle seguenti stringhe di input (o utilizza un formato simile per scegliere la tua scelta la tua avventura):

    • 1 10\n10 5\n10 13\n5 12\n5 19\n13 15\n12 20\n15 100
    • 15 2\n1 4\n2 12\n1 9\n3 1\n1 15\n9 3\n12 64\n4 10\n2 6\n80 100\n5 10\n6 24\n12 80\n6 150\n120 9\n150 120
  2. Incollalo nel prompt del violino di prova .

Codice formattato e commentato:

//Get Input from user
inputLines = prompt().split('\\n');

//Starting at 0, check for solutions with more moves
moves = 0;
while (!(solution = getSolution(moves++, 1)));

/**
 * Recursive function that returns the moves string or nothing if no
 * solution is available.
 *
 * @param numMoves - number of moves to check
 * @param startPage - the starting page to check
 * @param i - A counter.  Only included to make this a local variable.
 * @param line - The line being tested.  Only included to make this a local variable.
 */
function getSolution(numMoves, startPage, i, line) {
    //Only check for solutions if there are more than one moves left
    if (numMoves > 0) {
        //Iterate through all the lines
        for (i=0; text = inputLines[i++];) {
            line = text.split(' ');
            //If the line's start page matches the current start page
            if (line[0] == startPage) {
                //If the goal page is the to page return the step
                if (line[1] == 100) {
                    return text;
                }
                //If there is a solution in less moves from the to page, return that
                if (partialSolution = getSolution(numMoves - 1, line[1])) {
                    return line[0] + ' ' + partialSolution;
                }
            }
        }
    }
}

//Output the solution
alert(solution);

Per testare ( ATTENZIONE: loop infinito per input errato! ):

  1. Copia una delle seguenti stringhe di input (o utilizza un formato simile per scegliere la tua scelta la tua avventura):

    • 1 10\n10 5\n10 13\n5 12\n5 19\n13 15\n12 20\n15 100
    • 15 2\n1 4\n2 12\n1 9\n3 1\n1 15\n9 3\n12 64\n4 10\n2 6\n80 100\n5 10\n6 24\n12 80\n6 150\n120 9\n150 120
  2. Incollalo nel prompt del violino di prova .


Un buon uso della ricorsione qui. Mi piace anche il trucco di dare alla funzione argomenti extra solo per limitare l'ambito delle variabili :)
migimaru,

@migimaru: grazie! Una nota a varmargine correlata: questo problema è stato un problema per il debug fino a quando non ho appreso che le variabili JavaScript senza la parola chiave hanno portata globale :)
Briguy37

3

Ruby 1.9, 98

j=$<.map &:split
f=->*p,c{c=='100'?abort(p*' '):j.map{|a,b|a==c&&!p.index(b)&&f[*p,b,b]}}
f[?1,?1]

Ungolfed:

$lines = $<.map &:split
def f (*path)
    if path[-1] == '100' # story is over
        abort path.join ' ' # print out the path and exit
    else
        # for each jump from the current page
        $lines.each do |from, to|
            if from == path[-1] && !path.include?(to) # avoid loops
                # jump to the second page in the line
                f *path, to
            end
        end
    end
end

Ottimo uso dello splat lì.
migimaru,

3

Perl, 88 caratteri

sostanzialmente una versione perlizzata della voce di Clueless; pre-partite e post-partite sono divertenti :)

@t=<>;%s=(100,100);until($s{1}){for(@t){chomp;/ /;$s{$`}="$` $s{$'}"if$s{$'}}}print$s{1}

1

Python - 239 237 236

import sys
global d
d={}
for i in sys.stdin:
 a,b=[int(c) for c in i.split(' ')]
 try: d[b]+=[a]
 except: d[b]=[a]
def f(x,h):
 j=h+[x]
 if x==1:
  print ''.join([str(a)+" " for a in j[::-1]])
  exit()
 for i in d[x]:
  f(i,j)
f(100,[])

sfortunatamente, questa soluzione ricorsiva alla coda è vulnerabile ai loop nella "storia" ...

Utilizzo : cat ./test0 | ./sol.py Uscita per test case 1:

1 10 13 15 100

Uscita per test case 2:

1 15 2 12 80 100

0

Scala 2.9, 260 256 254 252 248 247 241 239 234 227 225 212 205 caratteri

object C extends App{var i=io.Source.stdin.getLines.toList.map(_.split(" "))
def m(c:String):String=(for(b<-i)yield if(b(1)==c)if(b(0)!="1")m(b(0))+" "+b(0)).filter(()!=).mkString
print(1+m("100")+" 100")}

Ungolfed:

object Choose extends App
{
    var input=io.Source.stdin.getLines.toList.map(_.split(" "))
    def findroute(current:String):String=
    (
        for(branch<-input)
        yield 
        if(branch(1)==current)
            if(branch(0)!="1")findroute(branch(0))+" "+branch(0)
    ).filter(()!=).mkString
    print(1+findroute("100")+" 100")
}

Uso:

Compila scalac filenamee corri con scala C. L'ingresso è preso via STDIN.
Per eseguire il ideone.com, il cambiamento object C extends Appper object Main extends Applicationeseguirlo come Scala 2.8.


0

PHP, 166 146 138 caratteri

$a[]=100;while(1<$c=$a[0])for($i=1;$i<$argc;$i++){list($p,$q)=explode(' ',$argv[$i]);if($q==$c)array_unshift($a,$p);}echo implode(' ',$a);

Ungolfed:

$a[]=100;
while(1<$c=$a[0])
    for($i=1;$i<$argc;$i++){
        list($p,$q)=explode(' ',$argv[$i]);
        if($q==$c)array_unshift($a,$p);
    }
echo implode(' ',$a);

Utilizzo:

php golf.php "1 10" "10 5" "10 13" "5 12" "5 19" "13 15" "12 20" "15 100"

Questo non produce alcun output per me quando lo eseguo dalla riga di comando in Windows o su ideone.com?
Gareth,

Funziona sul mio computer (Windows). Ho aggiunto un esempio di utilizzo. Tuttavia, non riesco a farlo funzionare su ideone.com
Alfwed,

Ah ... questo lo spiega, stavo cercando di inviare input STDINpiuttosto che come argomenti.
Gareth,

1
La genesi dell'utente φ ha proposto una modifica per correggere il conteggio dei caratteri. Potrebbe valere la pena mettere una versione golf senza spazi bianchi prima della versione non golfata, per soddisfare le aspettative della gente sulla convenzione locale.
Peter Taylor,

-1

Vorrei inserirli tutti in un array 2d e cercare tutti gli elementi con più loop, se riescono a raggiungere l'ultimo elemento quindi raccoglierei gli elementi correlati in ordine in un altro array di risultati e dai risultati sceglierei un array che è più piccolo .

EDIT => JAVA: ho anche usato la funzione ricorsiva, sotto il codice completo;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class Jumper {
    static int x = 0;
    public static ArrayList<ArrayList<String>> c = new ArrayList<ArrayList<String>>();  
    public static void main(String[] args) throws IOException {
       //Read from line and parse into array
        BufferedReader in = new BufferedReader(new FileReader("list.txt"));
        ArrayList<String> s = new ArrayList<String>();
        String line = null; 
        while ((line = in.readLine()) != null){s.add(line);}
        c.add(new ArrayList<String>());
            //When you get all items forward to method
        checkPages(0, s,Integer.parseInt(s.get(0).split(" ")[0]),Integer.parseInt(s.get(s.size()-1).split(" ")[1]));
    }   

    public static void checkPages (int level,ArrayList<String> list,int from, int dest){
        if(level <= list.size()){           
            for(int i=level;i<list.size();i++){
                int a = Integer.parseInt(list.get(i).split(" ")[0]);
                int b = Integer.parseInt(list.get(i).split(" ")[1]);
                if(a == from){
                    c.get(x).add(list.get(i));
                    if(b==dest){
                        c.add(new ArrayList<String>());
                        x++;
                    }else{
                        checkPages(i, list, b,dest);
                        c.get(x).remove(list.get(i));
                    }
                }

            }

        }
    }

}

Questo è code-golf, quindi è necessario fornire un'implementazione.
Gareth,

Ciao Gareth, dovrei partire ora, aggiungerò appena possibile quando arrivo a casa.
Burak,
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.