自分の冒険を選択してください


17

Choose Your Own Adventureブックは、読者がストーリーの結果に影響を与える決定を行う必要があるインタラクティブな文学の形式です。ストーリーの特定の時点で、読者には選択可能な複数のオプションがあり、それぞれが読者を本の異なるページに送ります。

たとえば、ファンタジーの設定では、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

ノート:

  • ジャンプのリストは、ユーザーがファイルまたは標準入力から入力します。最も便利な方を選択できます。
  • 入力には行ごとに1つのジャンプが含まれ、出発地と目的地は1つのスペースで区切られます。
  • 入力の行は、特定の順序であることが保証されていません。
  • 成功したパスはページ1で始まり、ページ100で終わります。
  • ゴールへのパスが少なくとも1つあると仮定できます。すべてのパスを見つける必要も、最短パスを見つける必要もありません。少なくとも1つ見つけてください。
  • 最小ページ番号は1です。最大ページ番号に制限はありません。(intの範囲に収まると想定できます。)
  • ループが存在する場合があります。たとえば、リストにはページ5から10、10から19、および19から5へのジャンプがあります。
  • 行き止まりがあるかもしれません。つまり、リンク先ページにジャンプする場所がない場合があります。
  • 逆に、到達不能なページがあるかもしれません。つまり、元のページはジャンプの宛先ではない可能性があります。
  • 1〜100のすべてのページ番号が使用されることが保証されているわけではありません。
  • 出力は、スペースで区切られた1から100までのページ番号の有効なルートで構成する必要があります。

これはコードゴルフであるため、最短の解決策が勝つことを忘れないでください!

編集:テスト用の別のサンプルを追加しました。


1
100ページからのジャンプがないと仮定できますか?
ピーターテイラー

はい、あなたはそれを仮定するかもしれません。
みぎまる

LispやAlloyのようなものがごく少数のcharでこれを達成できると感じているので、後で仕事を終えるときにそれを試みます。
ホセヌノフェレイラ

回答:


7

Golfscript、58 57文字

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

警告:これは非常に非効率的です。隣接行列を繰り返し二乗してからルートを探すことで機能します。Eグラフにエッジがある場合、最大2 Eの長さのすべてのパスを検出します(短いパスは多くの時間を検出します)。妥当な時間で最初のテストケースの結果が得られるはずですが、2番目のテストケースを試してみたい場合は、メモリの空き容量がいくつかあることを確認して、長い散歩をしてください。

合理的に効率的なソリューションが必要な場合は、67文字で提供します。

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

Golfscriptで行列乗算ができるとは思いませんでした!
みぎ丸

@migimaru、チューリングの強力な言語ですが、配列の処理には多くの欠点があります。
ピーターテイラー

それは本当だ。隣接行列がこのような小さなスペースに収まることを期待していなかったと思います;)
migimaru

@Peter申し訳ありませんが、これを試してみたところcat input | ruby1.9 golfscript.rb peter.gs、MacBookが非常に熱くなっていました。どうすれば実行できますか?
ガレス

3
@ガレス、うん。私が30分後にそれを殺したとき、それは最大2GBのメモリでした。警告をもう少し明確にします。
ピーターテイラー

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:ありがとう!関連する補足事項:この問題は、varキーワードのないJavaScript変数がグローバルスコープを持っていることがわかったまでデバッグするための
バグ作成者でした

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]

ゴルフをしていない:

$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

そこに感嘆符の非常に素晴らしい使用。
みぎまる

3

Perl、88文字

基本的に、Cluelessエントリのperlizedバージョン。試合前と試合後は楽しいです:)

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

残念ながら、この末尾再帰ソリューションは「ストーリー」のループに対して脆弱です...

使用法:cat ./test0 | ./sol.pyテストケース1の出力:

1 10 13 15 100

テストケース2の出力:

1 15 2 12 80 100

0

スカラ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で実行するには、Scala 2.8として実行するように変更object C extends Appobject Main extends Applicationます。


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で機能しない
-Alfwed

ああ...それはそれを説明します、私は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));
                    }
                }

            }

        }
    }

}

これはコードゴルフなので、実装を提供する必要があります。
ガレス

こんにちはガレス、私は家に着いたらすぐに出発します。
ブラク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.