Оберіть власну пригоду


17

Виберіть власні книги пригод - це форма інтерактивної літератури, де читач повинен приймати рішення, які впливають на результат історії. У певні моменти історії читач має кілька варіантів, які можна вибрати, кожен надсилає читача на іншу сторінку книги.

Наприклад, у фантастичній обстановці, можливо, доведеться визначитись на сторінці 14, чи слід заходити в таємничу печеру, "перестрибуючи" на сторінку 22, або досліджуючи сусідній ліс, переходячи на сторінку 8. Ці "стрибки" можна виразити як пари номерів сторінок, наприклад:

14 22
14 8

У більшості випадків історія є багато закінчень, але лише кілька хороших. Мета - орієнтуватися на історії, щоб досягти хорошого кінця.

Завдання:

Враховуючи список «стрибків» для даної книги, ваше завдання - визначити маршрут, який призведе до конкретного закінчення. Оскільки це досить легко, справжньою задачею є зробити це якомога менше символів.

Це код гольфу .

Зразок введення (де 1 - старт, а 100 - мета):

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

Вибірка зразка:

1 10 13 15 100

Зразок введення:

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

Вибірка зразка:

1 15 2 12 80 100

Примітки:

  • Список стрибків буде введений користувачем або з файлу, або з stdin. Ви можете вибрати те, що зручніше.
  • Вхід буде містити 1 стрибок на рядок, з початком та адресою, розділеними одним пробілом.
  • Рядки на вході не гарантуються в певному порядку.
  • Успішний шлях розпочнеться на сторінці 1 і закінчиться на сторінці 100.
  • Ви можете припустити, що є щонайменше 1 шлях до мети. Вам не потрібно знаходити всі шляхи, а також не потрібно знайти найкоротший. Просто знайдіть хоча б один.
  • Найменший номер сторінки буде 1. Найбільший номер сторінки не обмежується. (Ви можете припустити, що він впишеться в діапазон інт.)
  • Петлі можуть існувати. Наприклад, у списку можуть бути стрибки зі сторінки 5 на 10, 10 на 19 та 19 на 5.
  • Можуть бути тупики. Тобто на цільовій сторінці може нікуди переходити.
  • І навпаки, можуть бути недоступні сторінки. Тобто сторінка початку може не бути адресою жодних стрибків.
  • Не всі номери сторінок між 1 і 100 гарантовано використовуються.
  • Вихід повинен складатися з дійсного маршруту номерів сторінок, починаючи з 1 і закінчуючи 100, розділених пробілами.

Пам’ятайте, це кодовий гольф, тому найкоротше рішення виграє!

EDIT: Додано ще один зразок для тестування.


1
Чи можна припустити, що немає переходів зі сторінки 100?
Пітер Тейлор

Так, ви можете припустити, що.
migimaru

У мене є відчуття, що щось на кшталт шапочки чи сплаву могло б досягти цього за дуже мало часу, я спробую це пізніше, коли я зайду з роботи.
JoséNunoFerreira

Відповіді:


7

Гольфскрипт, 58 57 символів

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

Попередження : це надефективно. Він працює, повторюючи квадратику матриці суміжності та шукаючи маршрут; якщо Eна графіку є ребра, то він знайде кожен шлях довжиною до 2 Е (а коротший - знайдеться багато разів). Це має дати результат для першого тестового випадку в розумний час, але якщо ви хочете спробувати другий, переконайтеся, що у вас є кілька концертів пам'яті безкоштовно, і вирушайте на довгу прогулянку.

Якщо ви хочете досить ефективно рішення, то пропоную на 67 символів:

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

Я не розумів, що ви можете зробити множення матриць у Golfscript!
migimaru

@migimaru - це потужна мова Тьюрінга, однак багато недоліків в роботі з масивом може бути.
Пітер Тейлор

Це правда. Напевно, я просто не очікував, що матриці суміжності помістяться в такий невеликий простір;)
migimaru

@Peter Вибачте, я спробував запустити це, cat input | ruby1.9 golfscript.rb peter.gsі все, що трапилося, мій MacBook отримав дуже гаряче. Як мені це запустити?
Гарет

3
@Gareth, так. Коли я вбив його через півгодини, це було до 2 Гб пам'яті. Я зроблю попередження трохи більш явним.
Пітер Тейлор

14

Python, 232 213 157 143 135 132 символів (найкоротший шлях)

Ця реалізація може обробляти всі описані крайові випадки (петлі, тупики, осиротілі сторінки тощо) та гарантує, що вона знайде найкоротший шлях до кінця. Він заснований на алгоритмі найкоротшого шляху Джикстра.

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 символів

Це рекурсивне рішення, яке знаходить найкоротший шлях пригоди.

Кодовий гольф:

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)

Для тестування ( УВАГА: нескінченний цикл для поганого введення! ):

  1. Скопіюйте один із наступних рядків введення (або скористайтеся подібним форматом, щоб вибрати свій власний вибір пригоди):

    • 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. Вставте це у підказку тест-скрипки .

Форматований та коментований код:

//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);

Для тестування ( УВАГА: нескінченний цикл для поганого введення! ):

  1. Скопіюйте один із наступних рядків введення (або скористайтеся подібним форматом, щоб вибрати свій власний вибір пригоди):

    • 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. Вставте це у підказку тест-скрипки .


Тут непогано використовувати рекурсію. Мені також подобається хитрість надання функції додаткові аргументи просто для обмеження обсягу змінних :)
migimaru

@migimaru: Дякую! Пов’язана сторона зауваження: Ця проблема була помилкою для налагодження, поки я не дізнався, що змінні JavaScript без varключового слова мають глобальний обсяг :)
Briguy37

3

Рубін 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]

Безголовки:

$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

Дуже приємне використання шлапака там.
migimaru

3

Perl, 88 символів

в основному перероблена версія запису Clueless; попередні матчі та післяматчі - це весело :)

@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,[])

на жаль, це хвостово-рекурсивне рішення є вразливим до циклів у "історії" ...

Використання : кат. / Тест0 | ./sol.py Вихід для тестового випадку 1:

1 10 13 15 100

Вихід для тестового випадку 2:

1 15 2 12 80 100

0

Scala 2.9, 260 256 254 252 248 247 241 239 234 227 225 212 205 символів

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")}

Безголовки:

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")
}

Використання:

Компілюйте scalac filenameі запускайте з ним scala C. Введення приймається через STDIN.
Для запуску на ideone.com, зміни object C extends Appв object Main extends Applicationзапускати його як Scala 2.8.


0

PHP, 166 146 138 символів

$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);

Безумовно:

$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);

Використання:

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

Це не дає жодного результату для мене, коли я запускаю його з командного рядка у Windows або на ideone.com?
Гарет

Він працює на моєму комп’ютері (windows). Я додав приклад використання. Я не можу змусити його працювати на ideone.com, хоча
Альфвед

Ах ... це пояснює це, я намагався надсилати дані, STDINа не як аргументи.
Гарет

1
Користувач генезис φ запропонував редагувати, щоб виправити кількість символів. Можливо, варто поставити версію для гольфу без пробілів перед версією, що не має волі, щоб відповідати очікуванням людей від місцевої конвенції.
Пітер Тейлор

-1

Я б помістив їх у 2d масив і шукав би всі елементи з декількома петлями, якщо вони можуть дістатись до останнього, тоді я збирав би пов'язані елементи для іншого масиву результатів, а з результатів я вибрав би масив, який менший .

EDIT => JAVA: я також використовував рекурсивну функцію, повний код нижче;

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));
                    }
                }

            }

        }
    }

}

Це код-гольф, тому вам потрібно забезпечити реалізацію.
Гарет

Привіт, Гарет, я повинен піти зараз, я додаю якнайшвидше, коли приїду додому.
burak
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.