Chọn cuộc phiêu lưu của riêng bạn


17

Chọn sách Phiêu lưu của riêng bạn là một dạng văn học tương tác, nơi người đọc phải đưa ra quyết định ảnh hưởng đến kết quả của câu chuyện. Tại một số điểm nhất định trong câu chuyện, người đọc có nhiều lựa chọn có thể được chọn, mỗi người gửi người đọc đến một trang khác nhau trong cuốn sách.

Ví dụ, trong một bối cảnh giả tưởng, người ta có thể phải quyết định xem có nên mạo hiểm vào một hang động bí ẩn bằng cách "nhảy" sang trang 22 hay khám phá khu rừng gần đó bằng cách nhảy sang trang 8. Những "cú nhảy" này có thể được thể hiện như các cặp số trang, như vậy:

14 22
14 8

Trong hầu hết các trường hợp, có nhiều kết thúc cho câu chuyện nhưng chỉ có một vài cái tốt. Mục tiêu là điều hướng câu chuyện để đi đến một kết thúc tốt đẹp.

Bài tập:

Đưa ra một danh sách "các bước nhảy" cho một cuốn sách nhất định, nhiệm vụ của bạn là xác định lộ trình sẽ dẫn đến một kết thúc cụ thể. Vì việc này khá dễ, nên thử thách thực sự là làm càng ít nhân vật càng tốt.

Đây là mã golf .

Đầu vào mẫu (trong đó 1 là bắt đầu và 100 là mục tiêu):

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

Đầu ra mẫu:

1 10 13 15 100

Đầu vào mẫu:

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

Đầu ra mẫu:

1 15 2 12 80 100

Ghi chú:

  • Danh sách các bước nhảy sẽ được người dùng nhập vào, từ tệp hoặc stdin. Bạn có thể chọn bất cứ điều gì là thuận tiện nhất.
  • Đầu vào sẽ chứa 1 bước nhảy trên mỗi dòng, với điểm gốc và đích được phân tách bằng một khoảng trắng.
  • Các dòng trong đầu vào không được đảm bảo theo bất kỳ thứ tự cụ thể nào.
  • Một đường dẫn thành công sẽ bắt đầu ở trang 1 và kết thúc ở trang 100.
  • Bạn có thể cho rằng có ít nhất 1 đường dẫn đến mục tiêu. Bạn không cần tìm tất cả các đường dẫn, bạn cũng không cần tìm đường đi ngắn nhất. Chỉ cần tìm ít nhất một.
  • Số trang nhỏ nhất sẽ là 1. Không có giới hạn đối với số trang lớn nhất. (Bạn có thể cho rằng nó sẽ phù hợp với phạm vi của một int.)
  • Vòng lặp có thể tồn tại. Ví dụ: danh sách có thể có các bước nhảy từ trang 5 đến 10, 10 đến 19 và 19 đến 5.
  • Có thể có ngõ cụt. Đó là, một trang đích có thể không có nơi nào để nhảy tới.
  • Ngược lại, có thể có các trang không thể truy cập. Đó là, một trang gốc có thể không phải là đích của bất kỳ bước nhảy nào.
  • Không phải tất cả số trang trong khoảng từ 1 đến 100 đều được đảm bảo sử dụng.
  • Đầu ra của bạn phải bao gồm một tuyến số trang hợp lệ, bắt đầu bằng 1 và kết thúc bằng 100, cách nhau bởi khoảng trắng.

Hãy nhớ rằng, đây là mã golf, vì vậy giải pháp ngắn nhất sẽ thắng!

EDIT: Đã thêm một mẫu khác để thử nghiệm.


1
Chúng ta có thể cho rằng không có bước nhảy nào từ trang 100 không?
Peter Taylor

Vâng, bạn có thể cho rằng.
Migimaru

Tôi có cảm giác rằng một cái gì đó như lisp hoặc hợp kim có thể thực hiện điều này trong rất ít ký tự, tôi sẽ thử nó sau khi tôi nghỉ làm.
JoséNunoFerreira

Câu trả lời:


7

Golfscript, 58 57 ký tự

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

Cảnh báo : đây là siêu không hiệu quả. Nó hoạt động bằng cách lặp lại bình phương ma trận kề và sau đó tìm kiếm một tuyến đường; nếu có Ecác cạnh trong biểu đồ thì nó sẽ tìm mọi đường dẫn có độ dài lên tới 2 E (và các đường ngắn hơn nó sẽ tìm thấy rất nhiều lần). Nó sẽ cung cấp cho bạn một kết quả cho trường hợp thử nghiệm đầu tiên trong một thời gian hợp lý, nhưng nếu bạn muốn thử lần thứ hai, hãy chắc chắn rằng bạn đã có một vài hợp đồng bộ nhớ miễn phí và đi bộ lâu dài.

Nếu bạn muốn một giải pháp hợp lý hiệu quả thì tôi cung cấp ở 67 ký tự:

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

Tôi không nhận ra bạn có thể nhân ma trận trong Golfscript!
Migimaru

@migimaru, đó là một ngôn ngữ mạnh mẽ Turing, tuy nhiên nhiều thiếu sót trong việc xử lý mảng của nó có thể có.
Peter Taylor

Đúng. Tôi đoán tôi chỉ không mong đợi để thấy ma trận kề kề phù hợp với một không gian nhỏ như vậy;)
Migimaru

@Peter Xin lỗi, tôi đã thử chạy nó với cat input | ruby1.9 golfscript.rb peter.gsvà tất cả những gì đã xảy ra là MacBook của tôi thực sự rất nóng. Tôi nên chạy nó như thế nào?
Gareth

3
@Gareth, vâng. Khi tôi giết nó sau nửa giờ, nó đã lên tới 2GB bộ nhớ. Tôi sẽ làm cho cảnh báo rõ ràng hơn một chút.
Peter Taylor

14

Python, 232 213 157 143 135 132 ký tự (đường dẫn ngắn nhất)

Việc thực hiện này có thể xử lý tất cả các trường hợp cạnh được mô tả (vòng lặp, ngõ cụt, trang mồ côi, v.v.) và đảm bảo rằng nó sẽ tìm ra con đường ngắn nhất đến kết thúc. Nó dựa trên thuật toán đường đi ngắn nhất của 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 ký tự

Đây là một giải pháp đệ quy tìm ra con đường ngắn nhất trong cuộc phiêu lưu.

Code-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)

Để kiểm tra ( CẢNH BÁO: vòng lặp vô hạn cho đầu vào xấu! ):

  1. Sao chép một trong các chuỗi đầu vào sau (hoặc sử dụng định dạng tương tự để chọn riêng bạn chọn cuộc phiêu lưu của riêng bạn):

    • 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. Dán nó vào dấu nhắc của fiddle thử nghiệm .

Mã được định dạng và bình luận:

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

Để kiểm tra ( CẢNH BÁO: vòng lặp vô hạn cho đầu vào xấu! ):

  1. Sao chép một trong các chuỗi đầu vào sau (hoặc sử dụng định dạng tương tự để chọn riêng bạn chọn cuộc phiêu lưu của riêng bạn):

    • 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. Dán nó vào dấu nhắc của fiddle thử nghiệm .


Đẹp sử dụng đệ quy ở đây. Tôi cũng thích thủ thuật cung cấp cho hàm thêm đối số chỉ để giới hạn phạm vi của các biến :)
Migimaru

@migimaru: Cảm ơn! Một lưu ý bên lề liên quan: Vấn đề này là một lỗi để gỡ lỗi cho đến khi tôi biết rằng các biến JavaScript không có vartừ khóa có phạm vi toàn cầu :)
Briguy37

3

Hồng ngọc 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]

Ung dung:

$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

Sử dụng rất tốt của splat đó.
Migimaru

3

Perl, 88 ký tự

về cơ bản là một phiên bản sai lệch của mục Cluless '; trước trận đấu và sau trận đấu rất vui :)

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

1

Con trăn - 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,[])

thật không may, giải pháp đệ quy đuôi này dễ bị vòng lặp trong "câu chuyện" ...

Cách sử dụng : mèo ./test0 | ./sol.py Đầu ra cho trường hợp thử nghiệm 1:

1 10 13 15 100

Đầu ra cho trường hợp thử nghiệm 2:

1 15 2 12 80 100

0

Scala 2.9, 260 256 254 252 248 247 241 239 234 227 225 212 205 ký tự

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

Ung dung:

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

Sử dụng:

Biên dịch với scalac filenamevà chạy với scala C. Đầu vào được thực hiện thông qua STDIN.
Để chạy trên ideone.com, thay đổi object C extends Appđể object Main extends Applicationchạy nó như Scala 2.8.


0

PHP, 166 146 138 ký tự

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

Ung dung:

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

Sử dụng :

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

Điều này không tạo ra bất kỳ đầu ra nào cho tôi khi tôi chạy nó từ dòng lệnh trong windows hoặc trên ideone.com?
Gareth

Nó hoạt động trên máy tính của tôi (windows). Tôi đã thêm một ví dụ sử dụng. Mặc dù vậy, tôi không thể làm cho nó hoạt động trên ideone.com
Alfwed

À ... điều đó giải thích cho điều đó, tôi đã cố gắng gửi thông tin đầu vào STDINchứ không phải là đối số.
Gareth

1
Genesis người dùng đề xuất một chỉnh sửa để sửa số lượng ký tự. Có thể đáng để đặt một phiên bản chơi gôn mà không có khoảng trắng trước phiên bản không được phép, để đáp ứng mong đợi của mọi người về hội nghị địa phương.
Peter Taylor

-1

Tôi sẽ đặt tất cả chúng vào một mảng 2d và tìm kiếm tất cả các mục có nhiều vòng lặp, nếu chúng có thể đến mục cuối cùng thì tôi sẽ thu thập các mục liên quan theo thứ tự vào một mảng kết quả khác và từ kết quả tôi sẽ chọn một mảng nhỏ hơn .

EDIT => JAVA: Tôi cũng đã sử dụng hàm đệ quy, mã đầy đủ bên dưới;

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

            }

        }
    }

}

Đây là mã golf, vì vậy bạn cần cung cấp một triển khai.
Gareth

Xin chào Gareth, tôi nên rời đi ngay bây giờ tôi sẽ thêm asap khi tôi đến nhà.
burak
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.