Гольф-струны в Фурье


24

Вызов

Получив строку в качестве входных данных, бросьте вызов программе Фурье, которая выводит эту строку.

В Фурье нет простого способа вывести строку: вы должны пройти через каждый код символа и вывести его в виде символа.

Фурье

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

Персонаж из

a

Принимает значение аккумулятора в виде кода ASCII и выводит символ. Не меняет значение аккумулятора.

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

Номер из

o

Выводит значение аккумулятора. Не меняет значение аккумулятора.

Увеличение

^

Увеличьте аккумулятор на единицу.

Уменьшить

v

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

Добавлять

+x

Устанавливает аккумулятор в значение аккумулятора плюс значение х.

вычитать

-x

Устанавливает аккумулятор в значение аккумулятора минус значение х.

Умножение

*x

Устанавливает аккумулятор на значение аккумулятора, умноженное на значение x.

Делить

/x

Устанавливает аккумулятор в значение аккумулятора, деленное на значение х. (Обратите внимание, что это целочисленное деление, поэтому в 1/6результате 0)

Число

n

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

Заметка

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

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

Вы должны использовать только операторы, описанные выше. Поэтому ваша выведенная программа Фурье недействительна, если она использует любое из следующего (обратите внимание, что следующие награды разрешены для награды):

  • Повторите петли
  • Если заявления
  • переменные
  • случайный
  • Модульное
  • Пользовательский ввод
  • Больше / меньше чем операторы
  • Операторы равенства
  • Очисти экран
  • Временная задержка
  • Функции даты

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

Обратите внимание, что если vvв вашем коде есть символ, его следует заменить на -2. То же самое касается ^^замены его на +2.

Примеры

Если ввод 7n, то ожидаемая программа:

55a110a

Но вы можете сохранить один байт с

55a*2a

Другой способ

7o110a

Используя номер вне.


Точно так же, если ввод Hello, то ожидаемая программа:

72a101a108a108a111a

Вы можете уменьшить его на 3 байта (поскольку вывод не меняет аккумулятор):

72a101a108aa111a

Но подождите, мы можем использовать оператор сложения, сохраняя 2 байта:

72a101a+7aa+3a

Форматирование

Поскольку я буду использовать таблицу лидеров Stack Snippet Мартина Бюттнера, не могли бы вы отформатировать название следующим образом:

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

Затем вы можете поместить все, что вы хотите под заголовком.

выигрыш

Вы должны опубликовать длину программ Фурье (созданных вашим кодом) для вывода этого текстового файла и этого текстового файла . Ваша оценка - это общая длина обеих программ Фурье в байтах (не-ASCII-символы не используются в Фурье, поэтому это не имеет значения).

Человек с самыми низкими баллами побеждает. Если есть связь, побеждает самая короткая программа в байтах.

премия

Эта награда в 500 повторений предназначена для нового ответа, который играет на струнах с использованием любой из функций Фурье. Сюда входят переменные, циклы и операторы if и т. Д. Этот новый ответ не будет принят.

Leaderboard

Обратитесь к разделу форматирования выше:

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
Реальная проблема с необходимостью вывода всех оптимальных решений заключается в том, что для длительного ввода будет более оптимальных решений, чем атомов во вселенной.
Исаак

1
@orlp Отредактировал вывод всех оптимальных решений
Beta Decay

1
Должно ли это быть только для печати ASCII или какой-либо другой ASCII? И только 7-битный ASCII или полные байты?
orlp

1
Аккумулятор начинается с 0?
ASCIIThenANSI

Ответы:


9

Python, 14307118 байт

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

Определенно есть некоторые senarios, при которых это решение не является оптимальным, например, для 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 неправильный, см. Мои комментарии там.
Исаак

В нем было очень мало, но вы выиграли всего за 5 символов (вы и Разван связали, поэтому я использовал вашу длину кода в качестве тай-брейка)
Beta Decay

2
@BetaDecay Я никогда не видел, чтобы длина разрыва связи была релевантной между парой некоголивых программ.
Исаак

Да ... Я тоже: 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.

Это 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, что не правильно.
Исаак

Кроме того, я думаю, что вы неправильно используете аккумулятор. В elseпредложении основного цикла вы выбираете между использованием фактического значения аккумулятора и значения символа предыдущего символа. Вы не можете сделать последний выбор, если они разные, потому что это означает, что вы использовали oвремя до того, как накопитель не содержит значения предыдущего символа.
Исаак

Хорошо, оба должны быть исправлены сейчас. Благодарность!
Geobits

Когда я запускаю это на своем компьютере, я получаю 625474 для Гамлета и 13705922 для Бытия.
Исаак

@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; очевидно, он также пытается сравнить / увеличить / уменьшить;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.