Гольф-струни у Фур'є


24

Виклик

Враховуючи рядок як вхід, гольф запускає програму Фур'є, яка виводить її.

У Фур'є немає простого способу вивести рядок: вам потрібно пройти кожен код символів і вивести його як символ.

Фур’є

Мова заснована на акумуляторі, глобальній змінній, яка ініціалізується на 0 на початку програми. Цим використовується майже кожен оператор мовою. Тільки деякі не змінюють значення акумулятора.

Персонаж виходить

a

Приймає значення акумулятора як ASCII-код і видає символ. Не змінює значення акумулятора.

Якщо акумулятор більше 255, програма поверне помилку. Аналогічно, якщо акумулятор менше 0.

Нумерація

o

Виводить значення акумулятора. Не змінює значення акумулятора.

Збільшити

^

Збільшити акумулятор на одиницю.

Зменшити

v

Зменшіть акумулятор на один.

Додайте

+x

Встановлює акумулятор на значення акумулятора плюс значення x.

Відняти

-x

Встановлює акумулятор на значення акумулятора мінус значення х.

Помножте

*x

Встановлює акумулятор на значення акумулятора, помножене на значення x.

Розділити

/x

Встановлює акумулятор на значення акумулятора, поділене на значення x. (Зверніть увагу, що це ціле ділення, тому це 1/6призводить до 0)

Номер

n

Встановіть акумулятор на ціле число n.

Примітка

Тут xі nможе бути будь-яким цілим числом від 0до 2^32-1включно.

Більше інформації

Потрібно використовувати лише описані вище оператори. Тому ваша програма Fourier, що виводиться, є недійсною, якщо вона використовує будь-яке з наведеного нижче (зауважте, що для винагороди дозволені наступні оператори):

  • Повторіть петлі
  • Якщо заяви
  • Змінні
  • Випадкові
  • Модуло
  • Введення користувача
  • Більш / менше, ніж оператори
  • Оператори рівності
  • Очистити екран
  • Затримка в часі
  • Функції дати

Ваша програма може бути або повною програмою, або функцією, приймаючи вхід через STDIN, аргумент файлу або функції. Ви також можете взяти дані безпосередньо з Інтернету.

Зауважте, що якщо vvу вашому коді є, його слід замінити на -2. Те саме стосується ^^, замінивши його на +2.

Приклади

Якщо вхід є 7n, то очікувана програма:

55a110a

Але ви можете зберегти один байт за допомогою

55a*2a

Інший спосіб

7o110a

Використання номера з виходу.


Аналогічно, якщо вхід є Hello, тоді очікувана програма:

72a101a108a108a111a

Ви можете грати в гольф на 3 байти (оскільки вихід не змінює акумулятор):

72a101a108aa111a

Але зачекайте, ми можемо використовувати оператор додавання, економлячи 2 байти:

72a101a+7aa+3a

Форматування

Оскільки я використовую таблицю лідерів фрагментів стека Мартіна Бюттнера, будь ласка, ви можете відформатувати назву так:

# <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 Відредаговано вихід оптимальних рішень
Beta Decay

1
Чи повинен бути тільки друкований ASCII або будь-який тип ASCII? І лише 7-бітний ASCII або повний байт?
orlp

1
Акумулятор запускається при 0?
ASCIIThenANSI

Відповіді:


9

Пітон, 14307118 байт

601216 для Гамлета + 13705902 для Буття = 14307118

Однозначно є деякі сенарії, за яких це рішення не є оптимальним, наприклад, для того 1111, де воно виводитиметься 1111oна відміну від 11oo. Однак я думаю, що це майже оптимально.

Редагувати: збережено кілька байтів, покращивши 0o0oдо 0oo.

Ім'я файлу, що містить вхід, отримується на 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 символів (ви з Разваном зв'язали, так що я використовував вашу довжину коду як краватку)
бета-розпад

2
@BetaDecay Я ніколи не бачив, щоб перемикач довжини був релевантним між парою програм, що не мають вогків, раніше.
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
Це нормально, риба зазвичай росте з кожним оповіданням історії;)
Геобіт

Ну, це геніальний вибір мови: D
Beta Decay

Ваша програма не відповідала критеріям баунті (жодна з опублікованих відповідей не зробила), тому я присудив це вам, тому що мені подобається, що ви використовували <> <.
бета-розпад

8

Java, 14307140 байт

Гамлет - 601 218

Буття - 13 705 922

Ідея тут полягає в тому, щоб виконати всю роботу заздалегідь, зробивши карту символів-> персонажів. Тоді ви можете просто прокрутити і захопити найкоротші рядки.

Деякі винятки мають бути зроблені для цифр, тому я перевіряю їх у головному циклі. Він все ще швидкий, але обробляє більший тест за кілька секунд. Можливо, я зможу переробити цей розділ ще на пару байтів, але я впевнений, що він близький до оптимального.

Введення - це ім'я файлу як аргумент. Вихід записується у файл inputFilename_out.4, а кількість символів надсилається до STDOUT.

Це 1737 байтів для краватки, повністю без волі. Я можу багато чого в гольф, якщо це потрібно, але це все ще буде трохи великим.

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

Правильно, зараз потрібно виправити обидва. Спасибі!
Геобіць

Коли я запускаю це на своєму мохінгу, я отримую 625474 для Гамлета і 13705922 для Генезису.
isaacg

@isaacg Ви запускаєте його в одному файлі (з кінцями рядка)? Я раніше зіткнувся з проблемою із закінченнями рядків. Коли я запускаю моє і ваше на одному файлі, вони обидва показують опубліковані бали.
Геобіць

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 код + символ "а" = 4 символи), виконуючи основну операцію (+ - * /) на акумуляторі з числом між 2 і 9; очевидно, він також намагається порівняти / приріст / декремент;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.