选择自己的冒险


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

笔记:

  • 跳转列表将由用户从文件或标准输入中输入。您可以选择最方便的一种。
  • 输入将每行包含1个跳转,起点和终点之间用一个空格隔开。
  • 输入中的行不保证按任何特定顺序排列。
  • 成功的路径将从第1页开始,到第100页结束。
  • 您可以假设至少有1条通往目标的路径。您无需查找所有路径,也无需查找最短路径。只要找到至少一个。
  • 最小的页码为1。最大的页码没有限制。(您可以假定它会在int范围内。)
  • 可能存在循环。例如,该列表可能从第5页跳至10,从10跳至19和从19跳至5。
  • 可能会有死胡同。也就是说,目标页面可能没有任何地方可跳转。
  • 相反,可能存在无法访问的页面。也就是说,原始页面可能不是任何跳转的目的地。
  • 不能保证使用1到100之间的所有页码。
  • 您的输出应包含一个有效的页码路由,以1开始,以100结尾,以空格分隔。

请记住,这是代码高尔夫,所以最短的解决方案是成功的!

编辑:添加了另一个示例进行测试。


1
我们可以假设从第100页起没有跳转吗?
彼得·泰勒

是的,您可能会认为。
migimaru 2011年

我觉得像Lisp或Alloy这样的东西可以用很少的字符完成此操作,我下班后会再尝试。
JoséNunoFerreira

Answers:


7

Golfscript,58岁 57个字符

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

警告:这是超级无效的。它通过重复平方邻接矩阵,然后寻找路线来工作。如果图中有E边,则它将找到长度最大为2 E的每条路径(而较短的路径将发现很多次)。它应该在合理的时间内为您提供第一个测试用例的结果,但是如果您想尝试第二个测试用例,请确保您有几GB的可用存储空间并可以进行较长的步行。

如果您想要一个合理有效的解决方案,那么我提供67个字符:

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

我没有意识到您可以在Golfscript中做矩阵乘法!
migimaru

@migimaru,这是一种图灵功能强大的语言,但是其数组处理可能存在许多缺点。
彼得·泰勒

确实如此。我想我只是没想到会在这么小的空间中看到邻接矩阵;)
migimaru 2011年

@Peter Sorry,我尝试与此一起运行cat input | ruby1.9 golfscript.rb peter.gs,所有发生的是我的MacBook非常热。我应该如何运行?
加雷斯

3
@Gareth,是的。半小时后我将其杀死时,它的内存高达2GB。我将使警告更加明确。
彼得·泰勒

14

Python中,232个 213 157 143 135 132字符(最短路径)

此实现可以处理所有描述的边缘情况(循环,死角,孤立页面等),并保证它将找到到达终点的最短路径。它基于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个字符

这是一种递归解决方案,可找到经历冒险的最短路径。

代码化的:

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:谢谢!一个相关的旁注:这个问题是一个调试员,直到我了解到没有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

非常好使用splat。
migimaru

3

Perl,88个字符

基本上是“无头绪”条目的完整版本;赛前和赛后都很有趣:)

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

不幸的是,这种尾部递归解决方案容易受到“故事”中循环的影响。

用法:猫./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 上运行,请更改object C extends Appobject 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上使用它
Alfwed 2011年

啊...解释了这一点,我试图通过STDIN而不是作为参数发送输入。
加雷斯

1
用户创始φ建议进行修改以更正字符数。可能需要将不带空格的高尔夫球版放在非高尔夫球版之前,以满足人们对当地公约的期望。
彼得·泰勒

-1

我会将它们全部放入一个2d数组中,并使用多个循环搜索所有项目,如果它们可以到达最后一个项目,那么我将按顺序收集相关项目到另一个结果数组中,然后从结果中选择一个较小的数组。

编辑=> 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));
                    }
                }

            }

        }
    }

}

这是代码高尔夫,因此您需要提供一个实现。
Gareth

嗨,加雷斯,我现在应该离开,我到家时会尽快添加。
burak 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.