รหัส (นักดัด) กฎกอล์ฟ Golf


14

รหัสกอล์ฟเกี่ยวข้องกับคำตอบบางอย่างที่ทำให้กฏกติกามากขึ้นหรือน้อยลงด้วยการทำลายข้อ จำกัด ที่ผู้ท้าชิงรับหรือไม่ได้คิดและไม่ได้ระบุไว้ในกฎ หนึ่งในช่องโหว่ที่น่าสนใจเหล่านี้เป็นไปได้ในการส่งออกมากขึ้นกว่าที่ท้าทายขอที่จะได้รับผลที่ดีกว่า

เราสามารถเขียนตัวแก้รหัสกอล์ฟสากลที่พิมพ์ผลลัพธ์ที่ต้องการ - ถ้าคุณไม่สนใจว่ามันอาจต้องใช้เวลานานและเอาท์พุทสิ่งอื่น ๆ มากมายทั้งก่อนและหลัง

สิ่งที่เราต้องใช้ในการส่งออกคือลำดับที่รับประกันว่าจะมีส่วนประกอบทั้งหมดที่เป็นไปได้ สำหรับรหัสกอล์ฟนี้จะเป็นลำดับ Ehrenfeucht-Mycielski :

ลำดับเริ่มต้นด้วยสามบิต 010; แต่ละหลักต่อเนื่องจะเกิดขึ้นจากการหาคำต่อท้ายที่ยาวที่สุดของลำดับที่ปรากฏก่อนหน้านี้ภายในลำดับและการพึ่งพาบิตต่อไปนี้การปรากฏตัวก่อนหน้านี้ล่าสุดของคำต่อท้ายที่

การเรียงลำดับของบิตทุกอันเกิดขึ้นอย่างต่อเนื่องไม่สิ้นสุดบ่อยครั้งในลำดับ

ตัวเลขสองสามตัวแรกของลำดับคือ:

010011010111000100001111 ... (ลำดับA038219 ใน OEIS )

การรวมลำดับ 8 บิตเข้ากับไบต์เราจะได้รับเอาต์พุต ASCII ที่เราสามารถส่งออกไปยังหน้าจอหรือไฟล์และที่มีเอาต์พุต จำกัด ที่เป็นไปได้ทั้งหมด โปรแกรมจะเอาท์พุทชิ้นส่วนของ pi, เนื้อเพลงของ“ Never gonna give up” , ASCII art ที่ดี, ซอร์สโค้ดของมันเอง, และทุกอย่างที่คุณต้องการเอาท์พุท

สำหรับการทดสอบความถูกต้องนี่คือแฮชสำหรับ 256 ไบต์แรกของลำดับ:

MD5: 5dc589a06e5ca0cd9280a364a456d7a4
SHA-1: 657722ceef206ad22881ceba370d32c0960e267f

8 ไบต์แรกของลำดับในรูปแบบเลขฐานสิบหกคือ:

4D 71 0F 65 27 46 0B 7C

กฎ:

  • โปรแกรมของคุณจะต้องส่งออกลำดับ Ehrenfeucht-Mycielski (ไม่มีอะไรอื่น) รวม 8 บิตเป็นอักขระไบต์ / ASCII

  • โปรแกรมที่สั้นที่สุด (นับตัวอักษร) ชนะ ลบ 512 จากนับจำนวนตัวอักษรของคุณถ้าคุณจัดการเพื่อสร้างลำดับในเส้นเวลาต่อไบต์ที่สร้างขึ้น


คำต่อท้ายที่ยาวที่สุดใน 010 ซึ่งปรากฏก่อนหน้าในลำดับนั้นคือ 0 ใช่ไหม และลักษณะที่ปรากฏก่อนหน้านี้ล่าสุดคือเพียงแค่ 0 ที่สองและจนถึงตอนนี้ไม่มีอะไรตาม 0 ที่สองดังนั้นจึงไม่มีอะไรที่เราสามารถสร้างส่วนประกอบได้ ฉันไม่ใช่คนพูดภาษาอังกฤษ - บางทีฉันอาจเข้าใจผิด บทความวิกิพีเดียใช้คำเดียวกัน แต่มีลำดับที่ยาวกว่าดังนั้นฉันจะตั้งชื่อมันว่า "ล่าสุด ... ซึ่งมีผู้ติดตาม"
ผู้ใช้ที่ไม่รู้จัก

8
การเล่นลิ้น Pedantic: pi จะไม่ปรากฏขึ้น - เฉพาะสตริงจำกัดทุกอันเท่านั้นที่จะอยู่ในเอาต์พุต
Keith Randall

ฉันมีคำถามอื่น: การซ้ำซ้อนอาจทับซ้อนกันหรือไม่ ตัวอย่างเช่นใน 111, (1 [1) 1]?
ผู้ใช้ที่ไม่รู้จัก

@ KeithRandall: ฉันต้องการลำดับที่รับประกันว่าจะไม่มี 'Never gonna give up' และโปรดักชั่นประเภทเดียวกัน
ผู้ใช้ที่ไม่รู้จัก

2
มันอาจคุ้มค่าที่จะกล่าวถึงว่าการมีอยู่ของ "คำตอบ" ที่ฝังอยู่ในตำแหน่งที่ไม่ได้ระบุในสตริงที่ไม่มีที่สิ้นสุดไม่สามารถถือได้ว่าเป็น "เอาท์พุท" คำตอบนั้นแน่นอน นอกจากนี้ลำดับเฉพาะนี้เป็นเพียงตัวอย่างหนึ่งของลำดับที่แยกออกมา - มีลำดับที่มากมายเช่นนี้
res

คำตอบ:


7

C, –110 ตัวอักษร

โปรแกรมรุ่นนี้ใช้อัลกอริธึมเชิงเส้นตรงเพื่อสร้างลำดับ การลบ 512 จาก 402 chars ในโปรแกรมให้ผลรวมเป็นลบ 110

#define C v=calloc(7,8),v->p=p
#define G(F,K)u->F[d[K]]
#define S(F,T)G(f,T)=F,G(t,T)=T,G(n,T)=
struct{int p,f[2],t[2];void*n[2];}r,*u,*v,*w;char*d,c;p,b,h,i,j,k;
main(s){for(;d=++p-s?d:realloc(d,s*=2);){d[i=p]=b;c+=c+b;p%8||putchar(c);
for(u=&r;b=u->p,u->p=p,w=G(n,k=i);S(i,k)v=G(n,k),u=v)for(h=G(f,k),j=G(t,k);j>h;--i,--j)
if(d[i]-d[j]){S(i,k)C;u=v;S(h,j)w;S(0,i)C;b=w->p;goto x;}S(0,i)C;x:b=1-d[b+1];}}

ตามปัญหาโปรแกรมรันในลูปไม่สิ้นสุดซึ่งจำเป็นต้องมีการจัดสรรหน่วยความจำจำนวนมากและการใช้realloc()เพื่อให้ลำดับที่ต่อเนื่องกันสามารถนำไปสู่การกระจายตัวของฮีป คุณสามารถปรับปรุงการใช้หน่วยความจำของโปรแกรมโดยการแทนที่ในบรรทัดแรกกับcalloc(7,8) calloc(1,sizeof*v)สิ่งนี้จะช่วยโดยเฉพาะอย่างยิ่งในเครื่อง 32- บิตซึ่งมีแนวโน้มว่า 56 มีขนาดใหญ่เกินไปโดยใช้สองปัจจัย

รหัสไม่สามารถอ่านได้และไม่ใช่วิธีที่น่าสนใจ เพราะฉันขอโทษ ตรงไปตรงมาแม้แต่รุ่นที่ไม่ได้แต่งแต้มก็ยังไม่ชัดเจน:

#include <stdio.h>
#include <stdlib.h>

typedef struct branch branch;
typedef struct node node;

struct branch {
    int from, to;
    node *next;
};

struct node {
    int pos;
    branch br[2];
};

static node root = { 0 };

static unsigned char *data = NULL;
static int endpos = 0;
static int size = 1;

static node *mknode(void)
{
    node *n;

    n = calloc(1, sizeof *n);
    n->pos = endpos;
    return n;
}

static branch *getbranch(node *n, int p)
{
    return &n->br[data[p]];
}

static void setbranch(node *n, int from, int to, node *next)
{
    n->br[data[to]].next = next;
    n->br[data[to]].from = from;
    n->br[data[to]].to = to;
}

int main(void)
{
    node *u, *v, *w;
    int follower, from, i, i0, j;
    int out, b;

    out = b = 0;
    for (;;) {
        ++endpos;
        if (endpos == size) {
            size *= 2;
            data = realloc(data, size);
        }
        data[endpos] = b;
        out = (out << 1) | b;
        if (endpos % 8 == 0) {
            putchar(out);
            out = 0;
        }

        i = endpos;
        u = &root;
        for (;;) {
            follower = u->pos + 1;
            u->pos = endpos;
            w = getbranch(u, i)->next;
            if (!w)
                break;
            i0 = i;
            from = getbranch(u, i0)->from;
            for (j = getbranch(u, i0)->to ; j > from ; --j) {
                if (data[i] != data[j]) {
                    /* divide branch */
                    v = mknode();
                    setbranch(u, i, i0, v);
                    u = v;
                    setbranch(u, from, j, w);
                    setbranch(u, 0, i, mknode());
                    follower = w->pos + 1;
                    goto bitfound;
                }
                --i;
            }
            v = getbranch(u, i0)->next;
            setbranch(u, i, i0, v);
            u = v;
        }
        /* extend branch */
        setbranch(u, 0, i, mknode());

      bitfound:
        b = 1 - data[follower];
    }
}

(รหัส ungolfed ข้างต้นขึ้นอยู่กับรหัสที่เขียนโดย Grzegorz Herman และ Michael Soltys ตามที่อ้างอิงในคำอธิบายปัญหาและจากหน้าแรกของ Soltys )

ขอบคุณ @schnaader และ @res สำหรับการรายงานข้อบกพร่องในรุ่นเริ่มต้น


ดี! นั่นคือสิ่งที่ฉันหวังไว้ด้วย -512 โบนัส
schnaader

ความคิดใด ๆ ที่ทำให้เกิดปัญหาระบบล่ม รุ่นที่เล่นกอล์ฟไม่ได้ตีกอล์ฟและได้mallocรับการแก้ไขทั้งหมดจะหยุดเอาต์พุตหลังจากนั้นประมาณ 10,000 ไบต์และทำการจัดสรรหน่วยความจำต่อไปprog > out.datทำให้เกิดความผิดพลาดได้ทันทีด้วยการใช้หน่วยความจำเพียง ~ 700 KB ถ้าผมใส่printf("\n%i\n", size);หลังจากที่การส่งออกที่ใหญ่ที่สุดคือrealloc 4ระบบ: Windows 7 Prof. 64-Bit, 4 GB RAM, GCC 4.6.1
schnaader

(+1) ฉันพบว่าด้วย Ubuntu12.04 / gcc ทั้งสองโปรแกรมของคุณรวบรวมและสร้างผลลัพธ์ที่ถูกต้อง ... ด้วย Win7 / mingw / gcc ทั้งสองโปรแกรมรวบรวม แต่สร้างข้อผิดพลาดในการแบ่งเซ็กเมนต์ ... ด้วย Win7 / lcc เวอร์ชัน ungolfed ทำงานได้ แต่เวอร์ชัน golfed สร้างความผิดพลาดในการแบ่งส่วน
res

1
ฟังดูเหมือนการใช้ข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้นให้ฉัน แน่นอน - ฉันไม่สามารถเข้าถึงเครื่อง Windows ได้ แต่ valgrind แสดงปัญหา ดูเหมือนว่าฉันจะทำซ้ำข้อผิดพลาดนี้จากการใช้การอ้างอิงดั้งเดิมเช่นกัน โชคดีที่มันเป็นเรื่องง่าย ขอบคุณที่รายงาน!
breadbox

เยี่ยมมากใช้งานได้อย่างมีเสน่ห์ในขณะนี้
schnaader

6

Ruby, 109 104 101 94 ตัวอักษร

s=?0
loop{s=(s[/(.*).*\1/][/.#{$1}/]<?1??1:?0)+s
s.size&7<1&&$><<[s.reverse.to_i(2)].pack(?C)}

การนำไปใช้ใน Ruby โดยใช้นิพจน์ทั่วไปสำหรับการค้นหาคำต่อท้าย เนื่องจากใช้เวลาค่อนข้างนานจนกว่าหน่วยความจำไม่เพียงพอโปรแกรมจะต้องถูกยกเลิกโดยผู้ใช้

แก้ไข:ฉันเพิ่งสังเกตเห็นว่ามันเพียงพอที่จะเริ่มต้นด้วยลำดับ0ฉันเพิ่งสังเกตเห็นว่ามันจะเพียงพอที่จะเริ่มต้นด้วยลำดับ

แก้ไข 2:ข้อเสนอของบันทึกความละเอียด 2 ตัวละครบางคนอื่น ๆ เพราะเราไม่ได้มีการตัดออกจาก byte packเดียวก่อน


การใช้s=(s[/(.*).*\1/][/.#{$1}/]<?1??1:?0)+sจะบันทึกอีกสองอักขระ
res

@res มันใช้งานได้จริง ขอขอบคุณ.
Howard

คุณสามารถกำจัดวงเล็บที่อยู่รอบ ๆ ได้?Cไหม?
คดีของกองทุนโมนิกา

4

Perl, 95 ตัวอักษร

จริงๆแล้วฉันมีเวอร์ชั่นที่เหมาะสมครึ่งหนึ่งในตอนแรก จากนั้นเมื่อฉันเล่นกอล์ฟแต่ละรุ่นก็ช้าลง ช้าลงมากขึ้น

$|=$_="010";
y///c%8||print pack"B*",/(.{8})$/while/(.+)$(?(?{m|.*$^N(.)|})(?{$_.=1-$^N})|(?!))/

อักขระสามตัวแรก ( $|=) ไม่จำเป็นต้องพูดอย่างเคร่งครัด ... แต่หากไม่มีคุณจะต้องรอให้สคริปต์สร้าง 4096 ไบต์แบบเต็มให้เสร็จก่อนที่คุณจะเห็นผลลัพธ์ใด ๆ และนั่นจะใช้เวลาหลายชั่วโมง อาจจะเป็นศตวรรษ ฉันไม่แน่ใจ. ฉันไม่ได้พูดถึงว่าประสิทธิภาพของโปรแกรมประเภทนี้ลดลงเมื่อเวลาผ่านไปหรือไม่? ด้วยเหตุนี้ฉันจึงรู้สึกว่าถูกบังคับให้รวมพวกเขาไว้ในการนับ

ในอีกทางหนึ่งสคริปต์นี้มีหนึ่งใน regexes ที่น่าเกลียดที่สุดที่ฉันเคยสร้างดังนั้นฉันคิดว่าฉันภูมิใจในมัน


1
ไม่ต้องกังวลกับประสิทธิภาพอัลกอริทึมคือ O (N ^ 3) โดยไม่มีการปรับให้เหมาะสม โปรแกรม Delphi ง่าย ๆ ของฉันที่ฉันเขียนใช้เวลาประมาณ 30 วินาทีสำหรับ 256 ไบต์ แต่ประมาณหนึ่งชั่วโมงสำหรับ 1024 ไบต์ดังนั้นฉันจะสมมติว่า 4096 ไบต์ใช้เวลาหนึ่งหรือหลายวัน แน่นอนว่าการเพิ่มประสิทธิภาพของ RegEx และพื้นที่มีแนวโน้มที่จะทำให้แย่ลง :)
schnaader

สคริปต์ Perl เริ่มต้นของฉันใช้เวลา 10 วินาทีสำหรับ 256 ไบต์ รุ่นนี้ใช้เวลา 90 วินาที (หรือดูเหมือนจะเป็นการชะลอตัวเชิงเส้น)
breadbox
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.