Corde da golf a Fourier


24

Sfida

Data una stringa come input, golf giù il programma di Fourier che emette quella stringa.

In Fourier non esiste un modo semplice per generare una stringa: devi passare attraverso ogni codice carattere e inviarlo come carattere.

Fourier

La lingua si basa su un accumulatore, una variabile globale che viene inizializzata su 0 all'inizio del programma. Questo è usato da quasi tutti gli operatori nella lingua. Solo alcuni non modificano il valore dell'accumulatore.

Carattere fuori

a

Prende il valore dell'accumulatore come codice ASCII e genera il carattere. Non cambia il valore dell'accumulatore.

Se l'accumulatore è maggiore di 255, il programma restituirà un errore. Allo stesso modo se l'accumulatore è inferiore a 0.

Numero fuori

o

Emette il valore dell'accumulatore. Non cambia il valore dell'accumulatore.

Aumentare

^

Aumenta l'accumulatore di uno.

Diminuire

v

Ridurre l'accumulatore di uno.

Inserisci

+x

Imposta l'accumulatore sul valore dell'accumulatore più il valore di x.

Sottrarre

-x

Imposta l'accumulatore sul valore dell'accumulatore meno il valore di x.

Moltiplicare

*x

Imposta l'accumulatore sul valore dell'accumulatore moltiplicato per il valore di x.

Dividere

/x

Imposta l'accumulatore sul valore dell'accumulatore diviso per il valore di x. (Nota che questa è una divisione intera, quindi 1/6risulta 0)

Numero

n

Impostare l'accumulatore sull'intero n.

Nota

Qui, xe npuò essere qualsiasi numero intero da 0a 2^32-1compreso.

Maggiori informazioni

È necessario utilizzare solo gli operatori sopra descritti. Pertanto, il programma di Fourier in uscita non è valido se utilizza uno dei seguenti (tenere presente che i seguenti operatori sono ammessi per la taglia):

  • Ripeti i cicli
  • Se dichiarazioni
  • variabili
  • Casuale
  • Modulo
  • Input dell'utente
  • Maggiore / inferiore rispetto agli operatori
  • Operatori di uguaglianza
  • Schermo pulito
  • Ritardo
  • Funzioni data

Il tuo programma può essere un programma completo o una funzione, prendendo in input tramite STDIN, un file o argomenti di funzione. Puoi anche ricevere input direttamente da Internet.

Si noti che se vvnel codice è presente un codice, è necessario sostituirlo con -2. Lo stesso vale per ^^, sostituendolo con+2 .

Esempi

Se l'ingresso è 7n, quindi il programma previsto è:

55a110a

Ma puoi salvare un byte con

55a*2a

Un altro modo è

7o110a

Usando il numero fuori.


Allo stesso modo se l'input è Hello, il programma previsto è:

72a101a108a108a111a

Puoi giocare a golf di 3 byte (perché l'output non cambia l'accumulatore):

72a101a108aa111a

Ma aspetta, possiamo usare l'operatore addizione, risparmiando 2 byte:

72a101a+7aa+3a

Formattazione

Poiché userò la classifica dello Stack Snippet di Martin Büttner, per favore potresti formattare il titolo in questo modo:

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

Quindi, puoi mettere tutto ciò che desideri sotto il titolo.

vincente

Dovresti pubblicare la lunghezza dei programmi di Fourier (prodotti dal tuo codice) per produrre questo file di testo e questo file di testo . Il tuo punteggio è la lunghezza combinata di entrambi i programmi di Fourier in byte (i caratteri non ASCII non sono usati in Fourier, quindi non fa davvero la differenza).

Vince la persona con il punteggio più basso. Se c'è un pareggio, vince il programma più breve in byte.

generosità

Questa ricompensa da 500 rappresentanti è per una nuova risposta che gioca a golf sulle corde usando una qualsiasi delle funzioni di Fourier. Ciò include variabili, loop e istruzioni if, ecc. Questa nuova risposta non sarà accettata.

Classifica

Fare riferimento alla sezione di formattazione sopra:

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
Non credo che dover produrre tutte le soluzioni ottimali sia molto giusto / interessante.
Esclude

5
Il vero problema di dover produrre tutte le soluzioni ottimali è che per un input lungo, ci saranno soluzioni più ottimali degli atomi nell'universo.
isaacg,

1
@orlp Edito pubblicando tutte le soluzioni ottimali
Decadimento beta

1
Dovrebbe essere solo ASCII stampabile o qualsiasi tipo di ASCII? E solo ASCII a 7 bit o byte completi?
orlp,

1
L'accumulatore inizia da 0?
ASCIIThenANSI,

Risposte:


9

Python, 14307118 byte

601216 per Amleto + 13705902 per Genesi = 14307118

Esistono sicuramente alcuni senari in base ai quali questa soluzione non è ottimale, come ad esempio 1111, dove verrà prodotta 1111oal contrario11oo . Tuttavia, penso che sia quasi ottimale.

Modifica: salvato alcuni byte migliorando 0o0oa 0oo.

Il nome del file contenente l'input viene ricevuto su STDIN, emesso su STDOUT.

Risultati verificati con l'interprete ufficiale.

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 Beh, sono abbastanza sicuro che il risultato di Geobit sia sbagliato, vedi i miei commenti lì.
isaacg,

C'era molto poco, ma hai vinto solo 5 caratteri (tu e Razvan avete legato quindi ho usato la lunghezza del vostro codice come tiebreaker)
Beta Decay

2
@BetaDecay Non ho mai visto il tiebreaker di lunghezza rilevante tra una coppia di programmi non golfati prima.
Isaacg,

Sì ... Neanche a me: P
Decadimento beta

13

> <>, 14310665 byte

601398 per frazione + 13709267 per genesi

Questo è ancora un lavoro in corso e richiede molto tempo per il completamento.

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'<

È pazzesco, peccato però non sia ottimale.
orlp,

Sto lavorando su /, * e o, ma sta iniziando a prendere un po 'più di spazio.
Aaron,

18
Va bene, i pesci normalmente crescono ad ogni narrazione della storia;)
Geobits il

Bene, questa è una brillante scelta del linguaggio: D
Decadimento beta

Il tuo programma non si adattava ai criteri per la generosità (nessuna delle risposte postate lo faceva), quindi ti ho assegnato questo perché mi piace che tu abbia usato <> <.
Decadimento beta

8

Java, 14307140 byte

Amleto - 601.218

Genesi - 13.705.922

L'idea qui è di fare tutto il lavoro in anticipo, creando una mappa carattere-> carattere. Quindi puoi semplicemente scorrere e afferrare le stringhe più brevi.

Deve essere fatta un'eccezione per i numeri, quindi li controllo nel loop principale. Tuttavia, è ancora veloce e gestisce il test case più grande in pochi secondi. Io possa essere in grado di modificare questa sezione per un altro paio di byte, ma sono abbastanza sicuro che sia vicino alla ottimale.

L'input è un nome file come argomento. L'output viene scritto in un file inputFilename_out.4e il conteggio dei caratteri viene inviato a STDOUT.

Sono 1737 byte per il tiebreaker, completamente non golfato. Posso giocare a golf molto se necessario, ma sarà ancora un po 'grande.

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

}

Penso che questo non gestisca correttamente stringhe di cifre con zeri iniziali. Ad esempio, sull'input 01, credo che esca 01o, il che non è corretto.
isaacg,

Inoltre, penso che stai abusando dell'accumulatore. Nella elseclausola del ciclo principale, puoi scegliere se utilizzare il valore effettivo dell'accumulatore e il valore del carattere del carattere precedente. Non puoi fare quest'ultima scelta se i due sono diversi, perché ciò significa che hai usato oil tempo precedente e l'accumulatore non contiene il valore del personaggio precedente.
isaacg,

Bene, entrambi dovrebbero essere risolti ora. Grazie!
Geobits il

Quando eseguo questo sul mio machinge, ottengo 625474 per Amleto e 13705922 per Genesis.
isaacg,

@isaacg Lo stai eseguendo sullo stesso file (con le stesse terminazioni di riga)? Ho riscontrato un problema con le terminazioni di linea in precedenza. Quando eseguo il mio e il tuo sullo stesso file, entrambi mostrano i punteggi pubblicati.
Geobits il

2

PHP, 14307118 byte

601.216 (Amleto) + 13.705.902 (Bibbia)

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

Uscita di Fourier per Amleto

Funziona come segue:

  1. Scorre ogni carattere nell'input;
  2. Se c'è una sequenza di cifre iniziali diverse da 0, imposterà l'accumulatore su quel numero e lo emetterà come numero. Controlla anche cifre simili;
  3. Altrimenti, verifica se esiste un modo più breve di emettere il carattere corrente (piuttosto che il codice ASCII + simbolo "a" = 4 caratteri) eseguendo un'operazione di base (+ - * /) sull'accumulatore con un numero compreso tra 2 e 9; ovviamente, cerca anche di confrontare / incrementare / decrementare;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.