Struny do golfa w Fourier

24

Wyzwanie

Biorąc pod uwagę ciąg wejściowy, przejdź w dół do programu Fouriera, który wypisuje ten ciąg.

W Fourier nie ma łatwego sposobu na wyprowadzenie łańcucha: musisz przejść przez każdy kod znaku i wyprowadzić go jako znak.

Fourier

Język oparty jest na akumulatorze, zmiennej globalnej, która jest inicjowana na 0 na początku programu. Z tego korzysta prawie każdy operator w danym języku. Tylko niektóre nie zmieniają wartości akumulatora.

Wyróżnij się

a

Pobiera wartość akumulatora jako kod ASCII i wyprowadza znak. Nie zmienia wartości akumulatora.

Jeśli akumulator jest większy niż 255, program zwróci błąd. Podobnie, jeśli akumulator jest mniejszy niż 0.

Numeruj

o

Zwraca wartość akumulatora. Nie zmienia wartości akumulatora.

Zwiększać

^

Zwiększyć akumulator o jeden.

Zmniejszać

v

Zmniejsz akumulator o jeden.

Dodaj

+x

Ustawia akumulator na wartość akumulatora powiększoną o wartość x.

Odejmować

-x

Ustawia akumulator na wartość akumulatora minus wartość x.

Zwielokrotniać

*x

Ustawia akumulator na wartość akumulatora pomnożoną przez wartość x.

Podzielić

/x

Ustawia akumulator na wartość akumulatora podzieloną przez wartość x. (Zauważ, że jest to podział na liczby całkowite, więc 1/6wyniki 0)

Numer

n

Ustaw akumulator na liczbę całkowitą n.

Uwaga

Tutaj, xi nmoże być dowolną liczbą całkowitą od 0do 2^32-1włącznie.

Więcej informacji

Musisz korzystać wyłącznie z operatorów opisanych powyżej. Dlatego wyprowadzony program Fouriera jest nieprawidłowy, jeśli korzysta z któregokolwiek z poniższych (pamiętaj, że następujące nagrody są dozwolone dla nagrody):

  • Powtórz pętle
  • Jeśli oświadczenia
  • Zmienne
  • Losowy
  • Modulo
  • Wprowadzane przez użytkownika
  • Większy / mniejszy niż operatorzy
  • Operatorzy równości
  • Czysty ekran
  • Opóźnienie
  • Funkcje daty

Twój program może być pełnym programem lub funkcją, przyjmującą dane wejściowe przez STDIN, argumenty pliku lub funkcji. Możesz również pobierać dane bezpośrednio z Internetu.

Pamiętaj, że jeśli vvkod zawiera kod, należy go zastąpić -2. To samo dotyczy ^^zastąpienia go +2.

Przykłady

Jeśli dane wejściowe to 7n, oczekiwany program to:

55a110a

Ale możesz zaoszczędzić jeden bajt

55a*2a

Innym sposobem jest

7o110a

Używanie numeru.


Podobnie, jeśli dane wejściowe to Hello, oczekiwany program to:

72a101a108a108a111a

Możesz zagrać w golfa o 3 bajty (ponieważ wyjście nie zmienia akumulatora):

72a101a108aa111a

Ale poczekaj, możemy użyć operatora dodawania, oszczędzając 2 bajty:

72a101a+7aa+3a

Formatowanie

Ponieważ będę używać tabeli liderów Stack Snippet Martina Büttnera, proszę sformatować tytuł w następujący sposób:

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

Następnie możesz umieścić pod tytułem wszystko, co chcesz.

Zwycięski

Powinieneś opublikować długość programów Fouriera (wytworzonych przez twój kod), aby wyprowadzić ten plik tekstowy i ten plik tekstowy . Twój wynik to łączna długość obu programów Fouriera w bajtach (znaki spoza ASCII nie są używane w Fourierze, więc to tak naprawdę nie robi różnicy).

Osoba z najniższymi wynikami wygrywa. W przypadku remisu wygrywa najkrótszy program w bajtach.

Hojność

Ta nagroda za 500 powtórzeń to nowa odpowiedź, która gra w golfa przy użyciu dowolnej funkcji Fouriera. Obejmuje to zmienne, pętle i instrukcje if itp. Nowa odpowiedź nie zostanie zaakceptowana.

Tabela liderów

Patrz sekcja dotycząca formatowania powyżej:

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>

Rozpad beta
źródło
6
Nie wydaje mi się, aby tworzenie optymalnych rozwiązań było bardzo uczciwe / interesujące.
Wyklucza to
5
Prawdziwym problemem związanym z koniecznością uzyskania wszystkich optymalnych rozwiązań jest to, że w przypadku długich danych wejściowych będzie więcej optymalnych rozwiązań niż atomów we wszechświecie.
isaacg
1
@orlp Edytowano dane wyjściowe wszystkich optymalnych rozwiązań
Beta Decay
1
Czy powinien to być tylko do wydruku ASCII, czy jakikolwiek ASCII? I tylko 7-bitowy ASCII lub pełne bajty?
orlp
1
Czy akumulator zaczyna się od 0?
ASCIIThenANSI,

Odpowiedzi:

9

Python, 14307118 bajtów

601216 dla Hamleta + 13705902 dla Rodzaju = 14307118

Zdecydowanie istnieją pewne senarios, w których to rozwiązanie nie jest optymalne, na przykład w przypadku 1111, gdy będzie ono generowane 1111ow przeciwieństwie do tego 11oo. Myślę jednak, że jest prawie optymalna.

Edycja: Zapisano kilka bajtów, ulepszając 0o0odo 0oo.

Nazwa pliku zawierającego dane wejściowe jest odbierana na STDIN, a następnie wysyłana do STDOUT.

Wyniki zweryfikowane z oficjalnym tłumaczem.

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
źródło
@Shebang Cóż, jestem prawie pewien, że wynik Geobit jest zły, zobacz moje komentarze tam.
isaacg
Było bardzo mało, ale wygrałeś zaledwie 5 znaków (ty i Razvan związaliście się, więc użyłem twojego kodu jako rozstrzygającego)
Beta Decay
2
@BetaDecay Nigdy wcześniej nie widziałem, by długość tiebreakera była istotna między parą nie golfowych programów.
isaacg
Tak ... Ja też: P
Beta Decay
13

> <>, 14310665 bajtów

601398 dla wioski + 13709267 dla genezy

Jest to wciąż praca w toku i jej ukończenie zajmuje dużo czasu.

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'<
Aaron
źródło
To szalone małe, szkoda, że ​​nie jest optymalne.
orlp
Pracuję nad użyciem /, * i o, ale zaczyna to zajmować więcej miejsca.
Aaron
18
W porządku, ryby zwykle rosną z każdym opowiadaniem historii;)
Geobits
Cóż, jest to świetny wybór języka: D
Beta Decay
Twój program nie spełniał kryteriów nagrody (żadna z zamieszczonych odpowiedzi nie spełniała), więc przyznałem ci to, ponieważ uwielbiam to, że użyłeś <> <.
Beta Decay
8

Java, 14307140 bajtów

Hamlet - 601,218

Księga Rodzaju - 13 705 922

Chodzi o to, aby wykonać całą pracę z góry, tworząc mapę postaci>. Następnie możesz po prostu przejść przez pętlę i złapać najkrótsze struny.

Trzeba zrobić wyjątek dla cyfr, więc sprawdzam je w głównej pętli. Jest jednak nadal szybki i obsługuje większy przypadek testowy w ciągu kilku sekund. I może być w stanie dostosować tę sekcję na kilka bajtów więcej, ale jestem pewien, że to dość blisko optimum.

Dane wejściowe to nazwa pliku jako argument. Dane wyjściowe są zapisywane w pliku inputFilename_out.4, a liczba znaków jest wysyłana do STDOUT.

Jest to 1737 bajtów dla rozstrzygającego remisu, zupełnie nie golfisty. Mogę dużo zagrać w golfa, jeśli zajdzie taka potrzeba, ale nadal będzie trochę duży.

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

}
Geobity
źródło
Myślę, że to nie obsługuje poprawnie ciągów cyfr z zerami wiodącymi. Na przykład, na wejściu 01, wydaje mi się, że wypisuje 01o, co nie jest poprawne.
isaacg
Myślę też, że niewłaściwie używasz akumulatora. W elseklauzuli głównej pętli wybierasz między użyciem rzeczywistej wartości akumulatora a wartością znaku poprzedniego znaku. Nie możesz dokonać drugiego wyboru, jeśli oba są różne, ponieważ oznacza to, że wykorzystałeś owcześniej czas, a akumulator nie zawiera wartości poprzedniego znaku.
isaacg
Tak, oba powinny być teraz naprawione. Dzięki!
Geobits
Gdy uruchomię to na moim komputerze, dostaję 625474 dla Hamleta i 13705922 dla Genesis.
isaacg
@isaacg Czy używasz go w tym samym pliku (z takimi samymi zakończeniami linii)? Wcześniej miałem problem z zakończeniami linii. Kiedy uruchamiam moje i twoje na tym samym pliku, oba pokazują wyniki.
Geobits
2

PHP, 14307118 bajtów

601,216 (Hamlet) + 13 705 902 (Biblia)

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

Wyjście Fouriera dla Hamleta

Działa w następujący sposób:

  1. Iteruje po każdym znaku na wejściu;
  2. Jeśli istnieje ciąg niezerowych cyfr 0, ustawi akumulator na tę liczbę i wyśle ​​go jako liczbę. Sprawdza również podobne cyfry;
  3. W przeciwnym razie sprawdza, czy istnieje krótszy sposób wyprowadzenia bieżącego znaku (zamiast kodu ASCII + symbol „a” = 4 znaki), wykonując podstawową operację (+ - * /) na akumulatorze o liczbie od 2 do 9; oczywiście próbuje również porównać / zwiększyć / zmniejszyć;
Razvan
źródło