Senar golf di Fourier

24

Tantangan

Diberikan string sebagai input, mainkan program Fourier yang menampilkan string itu.

Di Fourier tidak ada cara mudah untuk menghasilkan string: Anda harus melalui setiap kode karakter dan menampilkannya sebagai karakter.

Fourier

Bahasa ini didasarkan pada akumulator, variabel global yang diinisialisasi ke 0 pada awal program. Ini digunakan oleh hampir setiap operator dalam bahasa ini. Hanya beberapa yang tidak mengubah nilai akumulator.

Karakter keluar

a

Mengambil nilai akumulator sebagai kode ASCII dan mengeluarkan karakter. Tidak mengubah nilai akumulator.

Jika akumulator lebih besar dari 255, program akan mengembalikan kesalahan. Demikian juga jika akumulator kurang dari 0.

Nomor keluar

o

Menghasilkan nilai akumulator. Tidak mengubah nilai akumulator.

Meningkatkan

^

Tambah akumulator satu per satu.

Mengurangi

v

Kurangi akumulator dengan satu.

Menambahkan

+x

Menetapkan akumulator ke nilai akumulator plus nilai x.

Mengurangi

-x

Menetapkan akumulator ke nilai akumulator dikurangi nilai x.

Berkembang biak

*x

Mengatur akumulator ke nilai akumulator dikalikan dengan nilai x.

Membagi

/x

Menetapkan akumulator ke nilai akumulator dibagi dengan nilai x. (Perhatikan bahwa ini adalah pembagian bilangan bulat, sehingga 1/6menghasilkan 0)

Jumlah

n

Atur akumulator ke integer n.

Catatan

Di sini, xdan ndapat setiap bilangan bulat dari 0ke 2^32-1inklusif.

Informasi lebih lanjut

Anda hanya harus menggunakan operator yang dijelaskan di atas. Karena itu, program Fourier yang Anda keluarkan tidak valid jika menggunakan salah satu dari yang berikut ini (perhatikan bahwa operator berikut diizinkan untuk mendapatkan hadiah):

  • Ulangi loop
  • Pernyataan jika
  • Variabel
  • Acak
  • Modulo
  • Input Pengguna
  • Lebih besar / kurang dari operator
  • Operator kesetaraan
  • Hapus layar
  • Waktu tunda
  • Fungsi tanggal

Program Anda bisa berupa program penuh atau fungsi, menerima input melalui STDIN, file atau argumen fungsi. Anda juga dapat mengambil input langsung dari Internet.

Perhatikan bahwa jika ada vvdalam kode Anda, Anda harus menggantinya dengan -2. Hal yang sama berlaku untuk ^^menggantikannya +2.

Contohnya

Jika inputnya 7n, maka program yang diharapkan adalah:

55a110a

Tetapi Anda dapat menyimpan satu byte dengan

55a*2a

Cara lain adalah

7o110a

Menggunakan nomor keluar.


Demikian pula jika inputnya Hello, maka program yang diharapkan adalah:

72a101a108a108a111a

Anda dapat menurunkannya dengan 3 byte (karena keluaran tidak mengubah akumulator):

72a101a108aa111a

Tapi tunggu, kita bisa menggunakan operator tambahan, menghemat 2 byte:

72a101a+7aa+3a

Memformat

Karena saya akan menggunakan leaderboard Stack Snippet Martin Büttner, bisakah Anda memformat judul seperti:

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

Kemudian, Anda dapat meletakkan apa pun yang Anda inginkan di bawah judul.

Kemenangan

Anda harus memposting panjang program Fourier (dihasilkan oleh kode Anda) untuk menampilkan file teks ini dan file teks ini . Skor Anda adalah panjang gabungan dari kedua program Fourier dalam byte (karakter non-ASCII tidak digunakan dalam Fourier sehingga tidak benar-benar membuat perbedaan).

Orang dengan skor terendah menang. Jika ada seri, program terpendek dalam byte akan menang.

Karunia

Hadiah 500 rep ini adalah untuk jawaban baru yang memanfaatkan string menggunakan salah satu fungsi Fourier. Itu termasuk variabel, loop dan jika pernyataan dll. Jawaban baru ini tidak akan diterima.

Papan peringkat

Lihat bagian pemformatan di atas:

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>

Peluruhan Beta
sumber
6
Saya tidak berpikir harus mengeluarkan semua solusi optimal sangat adil / menarik. Itu
mengesampingkan
5
Masalah sebenarnya dengan harus mengeluarkan semua solusi optimal adalah bahwa untuk input yang panjang, akan ada solusi yang lebih optimal maka ada atom di alam semesta.
isaacg
1
@ orlp Diedit menghasilkan semua solusi optimal
Beta Decay
1
Apakah hanya ASCII yang dapat dicetak, atau ASCII apa pun? Dan hanya ASCII 7-bit, atau byte penuh?
orlp
1
Apakah akumulator mulai dari 0?
ASCIIThenANSI

Jawaban:

9

Python, 14307118 byte

601216 untuk Hamlet + 13705902 untuk Genesis = 14307118

Pasti ada beberapa senarios di mana solusi ini tidak optimal, seperti untuk 1111, di mana ia akan menghasilkan 1111osebagai lawan 11oo. Namun, saya pikir itu hampir optimal.

Sunting: Disimpan beberapa byte dengan meningkatkan 0o0oke 0oo.

Nama file yang berisi input diterima pada STDIN, output ke STDOUT.

Hasil diverifikasi dengan penerjemah resmi.

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))
isaacg
sumber
@ Shebang Yah, saya cukup yakin hasil Geobit salah, lihat komentar saya di sana.
isaacg
Ada sangat sedikit di dalamnya, tetapi Anda menang dengan hanya 5 karakter (Anda dan Razvan terikat jadi saya menggunakan panjang kode Anda sebagai tiebreak)
Beta Decay
2
@ BetaDecay Saya belum pernah melihat panjang tiebreak yang relevan di antara sepasang program yang tidak diklik sebelumnya.
isaacg
Ya ... Saya juga: P
Beta Decay
13

> <>, 14310665 byte

601398 untuk dusun + 13709267 untuk genesis

Ini masih dalam proses dan membutuhkan banyak waktu untuk menyelesaikannya.

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'<
Harun
sumber
Itu gila kecil, sayang itu tidak optimal.
orlp
Saya sedang berusaha menggunakan /, * dan o, tetapi mulai mengambil lebih banyak tempat.
Aaron
18
Tidak apa-apa, ikan biasanya tumbuh dengan setiap cerita;)
Geobits
Nah, ini pilihan bahasa yang brilian: D
Beta Decay
Program Anda tidak sesuai dengan kriteria untuk hadiah (tidak ada jawaban yang diposting), jadi saya telah memberikan ini kepada Anda karena saya suka Anda menggunakan <> <.
Beta Decay
8

Java, 14307140 byte

Hamlet - 601.218

Kejadian - 13.705.922

Idenya di sini adalah melakukan semua pekerjaan di muka, dengan membuat peta karakter-> karakter. Kemudian Anda bisa melewati dan mengambil string terpendek.

Sedikit pengecualian harus dibuat untuk angka, jadi saya periksa mereka di loop utama. Ini masih cepat, dan menangani test case yang lebih besar dalam beberapa detik. Saya mungkin dapat mengubah bagian ini untuk beberapa byte lagi, tapi saya cukup yakin itu mendekati optimal.

Input adalah nama file sebagai argumen. Output ditulis ke file inputFilename_out.4, dan jumlah karakter dikirim ke STDOUT.

Ini adalah 1737 bytes untuk tiebreak, benar-benar tidak dikenali. Saya bisa bermain golf banyak jika diperlukan, tetapi masih akan sedikit besar.

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

}
Geobit
sumber
Saya pikir ini tidak menangani deretan angka dengan nol terkemuka dengan benar. Sebagai contoh, pada input 01, saya percaya itu keluaran 01o, yang tidak benar.
isaacg
Juga, saya pikir Anda menyalahgunakan akumulator. Dalam elseklausa loop utama, Anda memilih antara menggunakan nilai aktual akumulator dan nilai karakter karakter sebelumnya. Anda tidak dapat membuat pilihan yang terakhir jika keduanya berbeda, karena itu berarti Anda menggunakan owaktu sebelumnya, dan akumulator tidak mengandung nilai karakter sebelumnya.
isaacg
Benar, keduanya harus diperbaiki sekarang. Terima kasih!
Geobits
Ketika saya menjalankan ini di mesin saya, saya mendapatkan 625474 untuk Hamlet dan 13705922 untuk Genesis.
isaacg
@isaacg Apakah Anda menjalankannya pada file yang sama (dengan akhiran baris yang sama)? Saya mengalami masalah dengan garis akhir sebelumnya. Ketika saya menjalankan milik saya dan Anda pada file yang sama, mereka berdua menunjukkan skor yang diposting.
Geobits
2

PHP, 14307118 byte

601.216 (Hamlet) + 13.705.902 (Alkitab)

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

Output Fourier untuk Hamlet

Ia bekerja sebagai berikut:

  1. Iterasi setiap karakter dalam input;
  2. Jika ada urutan bukan angka 0 terkemuka, ia akan mengatur akumulator ke angka itu dan menampilkannya sebagai angka. Ini juga memeriksa angka yang sama;
  3. Jika tidak, periksa apakah ada cara yang lebih pendek untuk mengeluarkan karakter saat ini (daripada kode ASCII + "a" simbol = 4 karakter) dengan melakukan operasi dasar (+ - * /) pada akumulator dengan angka antara 2 dan 9; jelas, ia juga mencoba untuk membandingkan / menambah / mengurangi;
Razvan
sumber