Thử thách dự đoán nhánh


8

Mỗi ngày, mỗi phút, ... mỗi micro giây, nhiều quyết định được đưa ra bởi máy tính của bạn. Trong các ngôn ngữ cấp cao, chúng thường có dạng câu lệnh như if, whilefor, nhưng ở cấp độ cơ bản nhất, tồn tại các hướng dẫn ngôn ngữ máy gọi là hướng dẫn rẽ nhánh / nhảy . Bộ xử lý hiện đại xếp hàng hướng dẫn trong một đường ống , và điều này có nghĩa là bộ xử lý cần quyết định có nên lấp đầy đường ống bằng các hướng dẫn ngay sau nhánh (tức là không được thực hiện ) hoặc hướng dẫn tại đích nhánh.

Nếu bộ xử lý không đoán đúng, các hướng dẫn đã nhập sai vào đường ống cần phải được bỏ qua và các hướng dẫn chính xác phải được tìm nạp, gây ra độ trễ. Công việc của người dự đoán chi nhánh là thử và đoán xem liệu chi nhánh sẽ được thực hiện để tránh hành động tốn kém của việc nạp lại đường ống.

Bạn phải viết một công cụ dự đoán, sẽ đưa ra một chuỗi các quyết định trong quá khứ, đoán chính xác quyết định tiếp theo. Chương trình của bạn có thể được viết bằng bất kỳ ngôn ngữ nào, miễn là bạn chỉ định liên kết đến trình thông dịch của nó nếu đó là ngôn ngữ tối nghĩa / đánh gôn. Nó phải lấy lịch sử thực tế trong quá khứ làm đối số dòng lệnh đầu tiên của nó, nhưng nó sẽ không được cung cấp cho lần đoán đầu tiên của chuỗi. Sau đó, bạn phải trả lại dự đoán của mình bằng cách in nó ra thiết bị xuất chuẩn. Một quyết định có dạng "y" hoặc "n". Mỗi trường hợp thử nghiệm là một chuỗi gồm 72 quyết định, vì vậy bạn có thể giả sử rằng đối số lịch sử đã chỉ định sẽ không bao giờ dài hơn 71 ký tự. Ví dụ: thử nghiệm "Luân phiên 1":

ynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynyn

Bạn sẽ bị loại nếu chương trình của bạn:

  • không trả về kết quả trong vòng một giây
  • không trả về một yhoặc n(dòng mới không quan trọng và bị bỏ qua)
  • cố gắng sửa đổi bất kỳ mã hoặc tệp nào liên quan đến thử thách này, bao gồm mã của đối thủ khác
  • chứa bất cứ thứ gì độc hại

Bạn có thể sử dụng một tệp để duy trì nếu bạn muốn, nhưng nó phải được đặt tên duy nhất và phù hợp với các điều trên.

Đây là một , không phải . Chiến thắng sẽ được cấp bởi người dự đoán chi nhánh cho ứng cử viên có giải pháp dự đoán thành công hầu hết các nhánh trong toàn bộ bộ thử nghiệm. Các xét nghiệm:

yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,All yes
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn,All no
ynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynyn,Alternating 1
nnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyynnyy,Alternating 2
yyynnnyyynnnyyynnnyyynnnyyynnnyyynnnyyynnnyyynnnyyynnnyyynnnyyynnnyyynnn,Alternating 3
nnnnyyyynnnnyyyynnnnyyyynnnnyyyynnnnyyyynnnnyyyynnnnyyyynnnnyyyynnnnyyyy,Alternating 4
yyyyyynnnnnnyyyyyynnnnnnyyyyyynnnnnnyyyyyynnnnnnyyyyyynnnnnnyyyyyynnnnnn,Alternating 5
nnnnnnnnnnnnyyyyyyyyyyyynnnnnnnnnnnnyyyyyyyyyyyynnnnnnnnnnnnyyyyyyyyyyyy,Alternating 6
yyyyyyyyyyyyyyyyyynnnnnnnnnnnnnnnnnnyyyyyyyyyyyyyyyyyynnnnnnnnnnnnnnnnnn,Alternating 7
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyynnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn,Alternating 8
yynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyynyyn,2-1
ynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnnynnn,1-3
nyyyyynyyyyynyyyyynyyyyynyyyyynyyyyynyyyyynyyyyynyyyyynyyyyynyyyyynyyyyy,5-1
nnnnnnnnnnnynnnnnnnnnnnynnnnnnnnnnnynnnnnnnnnnnynnnnnnnnnnnynnnnnnnnnnny,1-11
nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyynyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,35-1
yynnnnyynnnnyynnnnyynnnnyynnnnyynnnnyynnnnyynnnnyynnnnyynnnnyynnnnyynnnn,2-4
ynnyyynyynnnynnyyynyynnnynnyyynyynnnynnyyynyynnnynnyyynyynnnynnyyynyynnn,1-2-3
ynynynynynynynynynynynynynynynynynynyyyyyyyyyyyyyyyyyynnnnnnnnnnnnnnnnnn,A1/A7
yyyyyynnnnnnyyyyyynnnnnnyyyyyynnnnnnnnyynnyynnyynnyynnyynnyynnyynnyynnyy,A5/A2
nnnnnnnnnnnnyyyyyyyyyyyynnnnnnnnnnnnyyyynnnnyyyynnnnyyyynnnnyyyynnnnyyyy,A6/A4
nyyyyynyyyyynyyyyynyyyyynyyyyynyyyyynyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,5-1/35-1
yyynnnyyynnnyyynnnnyyyyyyyyyyyyyyyyyyyyyyynyyyyynyyyyyyynnnnyynnnnyynnnn,A3/Y/5-1/2-4
yynnnnyynnnnyynnnnnyynnnynnyyynyynnnnnnynnnynnnynnnynnyynyynyynyynyynyyn,2-4/1-2-3/1-3/2-1

Toàn bộ các bài kiểm tra và chương trình chạy được đặt tại kho GitHub này . Đơn giản chỉ cần thêm dự đoán của bạn src/predictors.txtvào mẫu <name>,<command to run>và chạy main.py. Tôi đã cung cấp hai dự đoán rất cơ bản đã được thử nghiệm đơn giản. Tôi muốn giới thiệu chiều rộng cột ít nhất là 92 khi chạy trình chạy để có đầu ra đẹp. Nếu bạn tình cờ phát hiện ra bất kỳ lỗi nào với nó, xin vui lòng cho tôi biết. :)


3
Tôi đánh giá thấp thách thức này bởi vì theo tôi nó không nắm bắt được bản chất của một công cụ dự đoán nhánh. Ngay bây giờ, thách thức của bạn là về AI dự đoán chung hơn là dự đoán nhánh. Ít nhất là một thách thức dự đoán nhánh phải có các yêu cầu bộ nhớ rất nghiêm ngặt, lịch sử gia tăng và mọi quyết định phải là một chức năng của một địa chỉ bộ nhớ . Ngoài ra, thách thức của bạn không phải là khép kín.
orlp

4
Tôi thích thử thách này. Tôi nghĩ rằng một trường hợp thử nghiệm ngẫu nhiên hoàn toàn 50/50 là một ý tưởng tồi. Tuy nhiên, ngẫu nhiên 80/20 sẽ ổn, cũng như các trường hợp thử nghiệm khác bao gồm các phần ngẫu nhiên (như một số trường hợp thử nghiệm của bạn hiện đang làm). Tôi muốn giới thiệu bao gồm tất cả các trường hợp thử nghiệm của bạn trên bài viết của bạn.
Nathan Merrill

@NathanMerrill Cảm ơn, tôi đã xóa tất cả tính ngẫu nhiên khỏi các bài kiểm tra.
Doddy

1
@Doddy Xin lỗi, ý tôi là trò chơi đoán xu . Một người chơi tiếp tục tạo số không và số một, và người còn lại cố gắng đoán sau đó.
orlp

2
chúng ta có nên tránh tối ưu hóa cho các trường hợp thử nghiệm này? ai đó sẽ gửi một thuật toán "hoàn hảo" để so sánh lịch sử với kho kiểm tra đã biết và đạt 95% +
Sparr

Câu trả lời:


14

Máy nén (Ruby), điểm 1502/1656 90,7%

require 'zlib'
input = $*[0].to_s.chomp
recent_input = input[-35..-1] || input
puts recent_input.chars.uniq.min_by { |char| [Zlib::Deflate.deflate(input+char,9).size,-input.count(char),-input[-10..-1].to_s.count(char)] } || ?y

Kiểm tra xem chuỗi hiện tại sẽ dễ nén hơn nếu 'y' hoặc 'n' được thêm vào cuối. Nếu có thể nén bằng nhau, hãy sử dụng cái được hiển thị nhiều nhất.


7

DéjàVu (Mathicala), điểm 503/552 91.123%

If[Length[$ScriptCommandLine] < 2, Print["y"]; Exit[]];
input = Characters[$ScriptCommandLine[[2]]] /. {"y" -> 1, "n" -> 0};
For[test = Length[input], ! 
   ListQ[ker = FindLinearRecurrence[input[[-test ;;]]]], test--];
Print[LinearRecurrence[ker, input[[-test ;; Length[ker] - test - 1]], 
     test + 1][[-1]] /. {1 -> "y", _ -> "n"}];

Tìm kiếm một sự tái phát tuyến tính trong mẫu và tính toán thuật ngữ tiếp theo. Để thử nghiệm, lưu dưới dạng DéjàVu,MathematicaScript -script <file>.


2

Nhà sử học (Kotlin), điểm 1548/1656 93,478%

Dự đoán tương lai từ quá khứ.

fun main(args : Array<String>) {
    if (args.size == 0) {
        println('y')
        return
    }
    val history = args[0].reversed()
    var bestLength = 0
    var ys = 0
    var ns = 0
    for (i in 1..history.length-1) {
        var length = 0
        var j = i
        while (j < history.length) {
            if (history[j] == history[j - i]) {
                length++
            } else {
                break
            }
            j++
        }
        if (length > bestLength) {
            bestLength = length
            ys = 0
            ns = 0
        }
        if (length == bestLength) {
            if (history[i - 1] == 'y') {
                ys++
            } else {
                ns++
            }
        }
    }
    println(if (bestLength == 0) history[0] else if (ys >= ns) 'y' else 'n')
}

Biên dịch với: kotlinc Historian.kt
Chạy với:kotlin HistorianKt


1

Trình tìm mẫu (Java), điểm 1570/1656 (≈94,8%) 1532/1656 (≈92,5%)

Cải tiến nhẹ cho các mẫu phức tạp.

public class Main {

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.print("y");
            return;
        }
        System.out.print(new Pattern(args[0]).getNext());
    }

}

class Pattern {

    private String pattern;
    private int index;
    private int length;

    public Pattern(String string) {
        setPattern(string);
    }

    private void setPattern(String string) {
        if (string.length() == 0) {
            this.pattern = "y";
            this.index = 0;
            this.length = 1;
            return;
        }
        if (string.length() == 1) {
            this.pattern = string;
            this.index = 0;
            this.length = 1;
            return;
        }
        if (string.startsWith("ynnyyy")) {
            this.pattern = "ynnyyynyynnn";
            this.index = string.length() % 12;
            this.length = 12;
            return;
        }
        this.length = 0;
        char first = string.charAt(0);
        char current = first;
        boolean hasReverse = false;
        while (length < string.length() - 1 && !(hasReverse
                && current == first)) {
            hasReverse |= current != first;
            length++;
            current = string.charAt(length);
        }
        if (!(hasReverse && current == first)) {
            this.pattern = Character.toString(current);
            this.index = 0;
            this.length = 1;
            return;
        }
        this.pattern = string.substring(0, length);
        int i = length;
        while (i <= string.length() - length) {
            if (!string.substring(i, i + length).equals(pattern)) {
                setPattern(string.substring(i));
                return;
            }
            i += length;
        }
        this.index = string.length() % i;
        if (!string.substring(i).equals(pattern.substring(0, index))) {
            setPattern(string.substring(i));
        }
    }

    public char getNext() {
        char result = pattern.charAt(index);
        index = (index + 1) % length;
        return result;
    }

}

@TheNumberOne Bạn có chắc không? Nếu vậy, tôi sẽ đặt nó như là điểm số. Tốt công việc trên bài viết của bạn mặc dù; bạn thắng tôi!
TheCoffeeCup

Ah, bạn đã cải thiện hiệu suất của mình cho trường hợp thử nghiệm 1-2-3.
TheNumberOne

@TheNumberOne Vâng, sau một số thử nghiệm nghiêm trọng, tôi nhận ra rằng nó đang giết chết phần trăm của tôi. Câu hỏi không nói chính xác rằng những gì tôi đã làm không được phép ...
TheCoffeeCup

1

Factorio (Python3), điểm 1563/1656 94,38%

Các yếu tố trình tự từ trái sang phải thành một chuỗi các mẫu lặp lại và xen kẽ. Chủ yếu ủng hộ độ dài phù hợp dài hơn, nhưng chọn lặp lại trên các mẫu xen kẽ và ngắn hơn chiều dài chu kỳ dài hơn trong trường hợp hòa.

def main():
    if len(sys.argv) < 2:
        print('y')
        sys.stdout.flush()
        return
    history = sys.argv[1]
    while history:
        score = 0
        period = 0
        l = 0
        for p in range(1, len(history)):
            if history[0] == history[p]:
                m = lambda a, b: a == b
                s0 = 1
            else:
                m = lambda a, b: a != b
                s0 = 0
            s = 0
            for i in range(len(history)):
                j = i + p
                if j < len(history):
                    if not m(history[i], history[j]):
                        break
                    s += 1
            if s > score or s == score and s0 > score0:
                score = s
                score0 = s0
                period = p
                match = m
                l = j
        if period == 0:
            print(history[0])
            sys.stdout.flush()
            return
        if l >= len(history):
            break
        l = (l // period) * period
        history = history[l:]
    print('y' if match(history[-period], 'y') else 'n')
    sys.stdout.flush()

if __name__ == '__main__':
    main()

0

Lặp lại (Python), điểm 1173/1656 70,83%

Người dự đoán này chỉ đơn giản là đoán có nếu không có lịch sử, nếu không thì lặp lại kết quả thực tế trước đó.

import sys

if len(sys.argv) == 1:
   print "y"
else:
   print sys.argv[1][-1:]

! Repeater (Python), điểm 483/1656 29,17%

Nếu không có lịch sử, người dự đoán này sẽ đoán không, nếu không sẽ lặp lại điều ngược lại với kết quả thực tế cuối cùng.

import sys

if len(sys.argv) == 1:
   print "n"
else:
   if sys.argv[1][-1:] == "y":
      print "n"
   else:
      print "y"

2-toucher (Python), điểm 1087/1656 65,64%

Nếu có ít nhất hai kết quả trước đó giống nhau hoặc đã có một kết quả cho đến nay, dự đoán này sẽ chọn giống nhau. Nếu không có lịch sử, nó sẽ chọn "y". Nếu có ít nhất hai kết quả và hai kết quả gần đây nhất không giống nhau, nó sẽ chọn ngược lại với kết quả gần đây nhất.

import sys

if len(sys.argv) == 1:
   print "y"
elif len(sys.argv[1]) == 1:
   print sys.argv[1][-1:]
else:
   l = len(sys.argv[1])

   if sys.argv[1][l - 2:l - 1] == sys.argv[1][-1:]:
      print sys.argv[1][-1:]
   else:
      if sys.argv[1][-1:] == "y":
         print "n"
      else:
         print "y"

0

Tôi sẽ để lại một bình luận, nhưng yêu cầu 50 rep ngăn cản tôi.

Đã có thể nhận được một cải thiện nhỏ về câu trả lời của @ histocrat

Máy nén (Ruby), điểm 1504/1656 90,82%

require 'zlib'
input = $*[0].to_s.chomp
recent_input = input[-35..-1] || input
puts recent_input.chars.uniq.min_by { |char| [Zlib::Deflate.deflate(input+char,9).size,-input[-3..-1].to_s.count(char),-input.count(char)] } || ?y

Tôi đã điều chỉnh nó theo một số cách khác nhau và cải thiện + 0,12% là cách tốt nhất tôi tìm thấy.

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.