สายการเล่นกอล์ฟในฟูริเยร์


24

ท้าทาย

รับสตริงเป็นอินพุทให้ลงโปรแกรมฟูริเยร์ซึ่งส่งเอาต์พุตสตริงนั้น

ในฟูริเยร์ไม่มีวิธีที่ง่ายในการส่งออกสตริง: คุณต้องผ่านแต่ละรหัสตัวอักษรและเอาท์พุทที่เป็นตัวละคร

ฟูริเยร์

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

ตัวละครออกมา

a

รับค่าของตัวสะสมเป็นรหัส ASCII และส่งออกอักขระ ไม่เปลี่ยนค่าของตัวสะสม

หากสะสมมากกว่า 255 โปรแกรมจะส่งคืนข้อผิดพลาด เช่นเดียวกันหากตัวสะสมมีค่าน้อยกว่า 0

หมายเลขออก

o

ส่งออกค่าของตัวสะสม ไม่เปลี่ยนค่าของตัวสะสม

เพิ่ม

^

เพิ่มการสะสมหนึ่ง

ลดลง

v

ลดการสะสมโดยหนึ่ง

เพิ่ม

+x

ตั้งค่าตัวสะสมเป็นค่าของตัวสะสมบวกกับค่าของ x

ลบออก

-x

ตั้งค่าตัวสะสมเป็นค่าของตัวสะสมลบด้วยค่าของ x

คูณ

*x

ตั้งค่าตัวสะสมเป็นค่าของตัวสะสมคูณด้วยค่าของ x

การแบ่ง

/x

ตั้งค่าตัวสะสมเป็นค่าของตัวสะสมหารด้วยค่าของ x (โปรดทราบว่านี่คือการหารจำนวนเต็มดังนั้นจะได้1/6ผลลัพธ์0 )

จำนวน

n

ตั้งค่าตัวสะสมเป็นจำนวนเต็ม n

บันทึก

ที่นี่xและnสามารถเป็นจำนวนเต็มตั้งแต่0ถึง2^32-1รวมได้

ข้อมูลมากกว่านี้

คุณต้องใช้โอเปอเรเตอร์ที่อธิบายไว้ข้างต้นเท่านั้น ดังนั้นโปรแกรมฟูริเยร์เอาท์พุทของคุณจึงไม่ถูกต้องหากใช้สิ่งใดสิ่งหนึ่งดังต่อไปนี้ (โปรดทราบว่าตัวดำเนินการต่อไปนี้ได้รับอนุญาตสำหรับเงินรางวัล):

  • วนซ้ำซ้ำ
  • ถ้างบ
  • ตัวแปร
  • สุ่ม
  • modulo
  • อินพุตของผู้ใช้
  • มากกว่า / น้อยกว่าผู้ประกอบการ
  • ผู้ประกอบการความเท่าเทียมกัน
  • หน้าจอที่ชัดเจน
  • หน่วงเวลา
  • ฟังก์ชั่นวันที่

โปรแกรมของคุณอาจเป็นโปรแกรมเต็มรูปแบบหรือฟังก์ชั่นโดยรับอินพุตผ่าน STDIN ไฟล์หรืออาร์กิวเมนต์ของฟังก์ชัน คุณอาจป้อนข้อมูลโดยตรงจากอินเทอร์เน็ต

โปรดทราบว่าถ้ามีในรหัสของคุณคุณควรแทนที่ด้วยvv -2เดียวกันจะไปสำหรับแทนที่มันด้วย^^+2

ตัวอย่าง

หากอินพุตเป็น7nดังนั้นโปรแกรมที่คาดหวังคือ:

55a110a

แต่คุณสามารถบันทึกหนึ่งไบต์ด้วย

55a*2a

อีกวิธีคือ

7o110a

ใช้หมายเลขออก


ในทำนองเดียวกันถ้ามีการป้อนข้อมูลHelloแล้วโปรแกรมที่คาดหวังคือ:

72a101a108a108a111a

คุณสามารถตีมันลง 3 ไบต์ (เนื่องจากการส่งออกจะไม่เปลี่ยนการสะสม):

72a101a108aa111a

แต่เดี๋ยวก่อนเราสามารถใช้โอเปอเรเตอร์การเพิ่มเติมประหยัด 2 ไบต์:

72a101a+7aa+3a

การจัดรูปแบบ

เนื่องจากฉันจะใช้ลีดเดอร์บอร์ดย่อย Snippet ของ Martin Büttnerโปรดคุณจัดรูปแบบชื่อดังนี้:

# <Language name>, <length of total output> bytes

จากนั้นคุณสามารถใส่อะไรก็ได้ที่คุณต้องการด้านล่างชื่อ

การชนะ

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

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

เงินรางวัล

เงินรางวัล 500 ค่าตอบแทนนี้เป็นคำตอบใหม่ที่ใช้กับสายของฟังก์ชั่นของฟูริเยร์ ซึ่งรวมถึงตัวแปรลูปและถ้ามีคำสั่ง ฯลฯ คำตอบใหม่นี้จะไม่ได้รับการยอมรับ

ลีดเดอร์บอร์ด

อ้างถึงส่วนการจัดรูปแบบด้านบน:

var QUESTION_ID=55384;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),e.has_more?getAnswers():process()}})}function shouldHaveHeading(e){var a=!1,r=e.body_markdown.split("\n");try{a|=/^#/.test(e.body_markdown),a|=["-","="].indexOf(r[1][0])>-1,a&=LANGUAGE_REG.test(e.body_markdown)}catch(n){}return a}function shouldHaveScore(e){var a=!1;try{a|=SIZE_REG.test(e.body_markdown.split("\n")[0])}catch(r){}return a}function getAuthorName(e){return e.owner.display_name}function process(){answers=answers.filter(shouldHaveScore).filter(shouldHaveHeading),answers.sort(function(e,a){var r=+(e.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0],n=+(a.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0];return r-n});var e={},a=1,r=null,n=1;answers.forEach(function(s){var t=s.body_markdown.split("\n")[0],o=jQuery("#answer-template").html(),l=(t.match(NUMBER_REG)[0],(t.match(SIZE_REG)||[0])[0]),c=t.match(LANGUAGE_REG)[1],i=getAuthorName(s);l!=r&&(n=a),r=l,++a,o=o.replace("{{PLACE}}",n+".").replace("{{NAME}}",i).replace("{{LANGUAGE}}",c).replace("{{SIZE}}",l).replace("{{LINK}}",s.share_link),o=jQuery(o),jQuery("#answers").append(o),e[c]=e[c]||{lang:c,user:i,size:l,link:s.share_link}});var s=[];for(var t in e)e.hasOwnProperty(t)&&s.push(e[t]);s.sort(function(e,a){return e.lang>a.lang?1:e.lang<a.lang?-1:0});for(var o=0;o<s.length;++o){var l=jQuery("#language-template").html(),t=s[o];l=l.replace("{{LANGUAGE}}",t.lang).replace("{{NAME}}",t.user).replace("{{SIZE}}",t.size).replace("{{LINK}}",t.link),l=jQuery(l),jQuery("#languages").append(l)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",answers=[],page=1;getAnswers();var SIZE_REG=/\d+(?=[^\d&]*(?:&lt;(?:s&gt;[^&]*&lt;\/s&gt;|[^&]+&gt;)[^\d&]*)*$)/,NUMBER_REG=/\d+/,LANGUAGE_REG=/^#*\s*([^,]+)/;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table></div> <tbody id="languages"> </tbody> </table></div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody></table>


6
ฉันไม่คิดว่าการส่งออกโซลูชั่นที่ดีที่สุดทั้งหมดนั้นยุติธรรม / น่าสนใจมาก มันออกกฎการใช้งานทั้งหมดยกเว้นแรงเดรัจฉาน ...
orlp

5
ปัญหาที่แท้จริงของการแก้ปัญหาที่ดีที่สุดคือการป้อนข้อมูลเป็นระยะเวลานานจะมีทางออกที่ดีที่สุดจากนั้นก็มีอะตอมในจักรวาล
isaacg

1
@orlp แก้ไขการส่งออกทางออกที่ดีที่สุดทั้งหมด
สลายตัวเบต้า

1
ควรเป็น ASCII ที่พิมพ์ได้หรือ ASCII ประเภทใดเท่านั้น และ ASCII 7 บิตเท่านั้นหรือเต็มไบต์?
orlp

1
ตัวสะสมเริ่มต้นที่ 0 หรือไม่?
ASCIIThenANSI

คำตอบ:


9

Python ขนาด 14307118 ไบต์

601216 สำหรับ Hamlet + 13705902 สำหรับ Genesis = 14307118

มีบางรุ่นที่แน่นอนซึ่งโซลูชันนี้ไม่เหมาะสมเช่นเพื่อ1111ที่จะให้ผลลัพธ์1111oเมื่อเทียบกับ11ooเมื่อเทียบกับอย่างไรก็ตามฉันคิดว่ามันเกือบจะดีที่สุดแล้ว

แก้ไข: บันทึกไม่กี่ไบต์โดยการปรับปรุงการ0o0o0oo

ชื่อของไฟล์ที่มีอินพุตได้รับบน STDIN, ส่งออกไปยัง STDOUT

ผลการตรวจสอบกับล่ามอย่างเป็นทางการ

def opt_str(char, acc):
    opts = []
    char_num = ord(char)
    opts.append(str(char_num))
    if 0 < char_num - acc < 10:
        opts.append('+' + str(char_num - acc))
    if 0 < acc - char_num < 10:
        opts.append('-' + str(acc - char_num))
    if char_num - acc == 1:
        opts.append('^')
    if acc - char_num == 1:
        opts.append('v')
    if acc == char_num:
        opts.append('')
    if acc and char_num % acc == 0:
        opts.append('*' + str(char_num//acc))
    try:
        if acc // (acc // char_num) == char_num:
            opts.append('/' + str(acc // char_num))
    except:
        pass
    return [opt for opt in opts if len(opt) == len(min(opts, key=len))]

acc = 0
result = []
pos = 0
with open(input(), "r") as myfile:
        in_str = myfile.read()
while pos < len(in_str):
    i = in_str[pos]
    pos += 1
    if i in '0123456789':
        if i != '0':
            while pos < len(in_str) and in_str[pos] in '0123456789':
                i += in_str[pos]
                pos += 1
        if i == str(acc):
            result.append('o')
        else:
            result.append(i + 'o')
        acc = int(i)
    else:
        opts = opt_str(i, acc)
        result.append(opts[0] + 'a')
        acc = ord(i)
print(''.join(result))

@Shebang ดีฉันค่อนข้างแน่ใจว่าผลลัพธ์ของ Geobit ไม่ถูกต้องดูความคิดเห็นของฉันที่นั่น
isaacg

มีน้อยมากในนั้น แต่คุณชนะเพียง 5 ตัวอักษร (คุณและ Razvan ผูกดังนั้นฉันใช้ความยาวรหัสของคุณเป็น tiebreaker)
Beta Decay

2
@BetaDecay ฉันไม่เคยเห็น tiebreaker ความยาวนั้นมีความเกี่ยวข้องกันระหว่างโปรแกรมที่ไม่ได้รับการดัดแปลงมาก่อน
isaacg

ใช่ ... ฉันไม่: P
เบต้าสลายตัว

13

> <>, 14310665 ไบต์

601398 สำหรับหมู่บ้านเล็ก ๆ + 13709267 สำหรับแหล่งกำเนิด

ยังคงอยู่ระหว่างดำเนินการและใช้เวลาในการดำเนินการให้เสร็จสมบูรณ์

v
0
>i:0(?;:r-:?!v:0a-)?v     v
  >~:v       ~      >:a(?v>
 :1+?v~'v'o  v      o'^'~\:0)?v
     >n      vno'+'      ^?=1:<
^        o'a'<

มันเล็กไปเสียแล้วความละอายมันก็ไม่เหมาะ
orlp

ฉันกำลังทำงานโดยใช้ /, * และ o แต่มันเริ่มที่จะเพิ่มมากขึ้น
แอรอน

18
ไม่เป็นไรปลาปกติจะโตขึ้นตามการบอกเล่าแต่ละเรื่อง;)
Geobits

นี่เป็นตัวเลือกภาษาที่ยอดเยี่ยม: D
Beta Decay

โปรแกรมของคุณไม่ตรงกับเกณฑ์สำหรับความโปรดปราน (ไม่มีคำตอบที่โพสต์เลย) ดังนั้นฉันจึงให้รางวัลกับคุณเพราะฉันชอบที่คุณใช้ <> <
สลายตัวเบต้า

8

Java, 14307140 ไบต์

หมู่บ้าน - 601,218

ปฐมกาล - 13,705,922

ความคิดที่นี่คือการทำงานทั้งหมดล่วงหน้าโดยการทำแผนที่ตัวละคร> ตัวละคร จากนั้นคุณสามารถวนซ้ำและคว้าสตริงที่สั้นที่สุด

ต้องมีข้อยกเว้นเล็กน้อยสำหรับตัวเลขดังนั้นฉันจะตรวจสอบพวกเขาในลูปหลัก แม้ว่าจะยังเร็วและจัดการกรณีทดสอบที่ใหญ่กว่าในไม่กี่วินาที ฉันอาจจะปรับแต่งส่วนนี้อีกสองสามไบต์ แต่ฉันค่อนข้างแน่ใจว่ามันใกล้เคียงที่สุด

อินพุตเป็นชื่อไฟล์เป็นอาร์กิวเมนต์ เอาต์พุตถูกเขียนลงในไฟล์inputFilename_out.4และจำนวนอักขระถูกส่งไปยัง STDOUT

นี่คือ 1,737 ไบต์สำหรับ tiebreaker ที่ไม่ได้รับการตีอย่างสมบูรณ์ ฉันสามารถเล่นกอล์ฟได้มากถ้าจำเป็น แต่มันยังคงใหญ่ไปหน่อย

import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Paths;
import java.text.NumberFormat;

public class FourierMapper {
    public static void main(String[] args) throws Exception {
        FourierMapper fm = new FourierMapper();
        fm.createMap();
        String filename = args.length>0? args[0]:"bible.txt";
        String out = fm.fourierize(filename);
        System.out.println(out.length());
        Files.write(Paths.get(filename + "_out.4"), out.getBytes(), new OpenOption[]{});
    }

    String[][] map = new String[9999][256];
    void createMap(){
        for(int from=0;from<9999;from++){
            for(int to=0;to<256;to++){
                if(to<10||from<1){
                    map[from][to] = ""+to;
                } else if(to==from){
                    map[from][to] = "";
                } else if(to-from==1){
                    map[from][to] = "^";
                } else if(to-from==-1){
                    map[from][to] = "v";
                } else if(to>99){               
                    if(to%from<1){
                        map[from][to] = "*"+(to/from);
                    } else if(to>from&&to-from<10){
                        map[from][to] = "+"+(to-from);
                    } else if(from>to&&from-to<10){
                        map[from][to] = "-"+(from-to);
                    } else {
                        map[from][to] = ""+to;
                    }
                } else {
                    map[from][to] = ""+to;
                }
            }
        }
    }

    String fourierize(String filename) throws Exception{
        StringBuilder out = new StringBuilder();
        byte[] in = Files.readAllBytes(Paths.get(filename));
        String whole = new String(in);
        out.append(in[0] + "a");
        int number = -1;
        for(int i=1;i<in.length;){
            if(in[i]<58&&in[i]>47){
                number = in[i]==48?0:((Number)NumberFormat.getInstance().parse(whole.substring(i,i+4))).intValue();
                out.append(""+number+"o");
                i += (""+number).length();
            } else {
                if(number<0)
                    out.append(map[in[i-1]][in[i]]+"a");
                else
                    out.append(map[number][in[i]]+"a");
                number = -1;
                i++;
            }
        }
        return out.toString();
    }

}

ฉันคิดว่านี่ไม่ได้จัดการสตริงของตัวเลขด้วยเลขศูนย์นำอย่างถูกต้อง ตัวอย่างเช่นในอินพุต01ฉันเชื่อว่าเอาต์พุต01oซึ่งไม่ถูกต้อง
isaacg

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

ใช่แล้วทั้งคู่ควรได้รับการแก้ไขแล้ว ขอบคุณ!
Geobits

เมื่อฉันเรียกใช้สิ่งนี้บน machinge ของฉันฉันได้รับ 625474 สำหรับ Hamlet และ 13705922 สำหรับ Genesis
isaacg

@isaacg คุณกำลังเรียกใช้ไฟล์เดียวกัน (ที่ลงท้ายด้วยบรรทัดเดียวกัน) หรือไม่? ฉันพบปัญหากับการสิ้นสุดบรรทัดก่อนหน้านี้ เมื่อฉันเรียกใช้ฉันและของคุณในไฟล์เดียวกันพวกเขาทั้งสองแสดงคะแนนที่โพสต์
Geobits

2

PHP, 14307118 ไบต์

601,216 (หมู่บ้านเล็ก) + 13,705,902 (พระคัมภีร์)

function f($file) {
    $text = file_get_contents($file);

    $a = 0;

    for ($i = 0; $i < strlen($text); $i++) {
        $chr = $text[$i];

        if (ctype_digit($chr)) {
            while ($chr && isset($text[$i + 1]) && ctype_digit($text[$i + 1])) {
                $chr .= $text[$i + 1];
                $i++;
            }

            if ($a == (int)$chr) {
                print "o";
            }
            else {
                $a = (int)$chr;
                print $chr . "o";
            }

            continue;
        }

        $ord = ord($chr);

        $mapping = array(
            '' => $a,
            '^' => $a + 1,
            'v' => $a - 1
        );

        for ($j = 2; $j <= 9; $j++) {
            $mapping["+$j"] = $a + $j;
            $mapping["-$j"] = $a - $j;
            $mapping["*$j"] = $a * $j;
            $mapping["/$j"] = $a / $j;
        }

        foreach ($mapping as $op => $value) {
            if ($value === $ord) {
                $a = $value;
                print $op . "a";
                continue 2;
            }
            else if ($value . '' === $chr) {
                $a = $value;
                print $op . "o";
                continue 2;
            }
        }

        $a = $ord;
        print $ord . "a";
    }
}

ผลผลิตฟูริเยร์สำหรับแฮมเล็ต

มันทำงานได้ดังต่อไปนี้:

  1. วนซ้ำอักขระแต่ละตัวในอินพุต
  2. หากมีลำดับของตัวเลขนำหน้าไม่ใช่ 0 มันจะตั้งตัวสะสมไปยังหมายเลขนั้นและส่งออกเป็นจำนวน นอกจากนี้ยังตรวจสอบตัวเลขที่คล้ายกัน
  3. มิฉะนั้นตรวจสอบว่ามีวิธีที่สั้นกว่าของการส่งออกตัวละครปัจจุบัน (มากกว่ารหัส ASCII + "a" สัญลักษณ์ = 4 ตัวอักษร) โดยการดำเนินการขั้นพื้นฐาน (+ - * /) ในการสะสมที่มีจำนวนระหว่าง 2 และ 9; เห็นได้ชัดว่ามันยังพยายามเปรียบเทียบ / เพิ่ม / ลดลง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.