Cordes de golf à Fourier

24

Défi

Étant donné une chaîne en entrée, faites défiler le programme Fourier qui produit cette chaîne.

Dans Fourier, il n'y a pas de moyen facile de sortir une chaîne: vous devez parcourir chaque code de caractère et le sortir en tant que caractère.

Fourier

Le langage est basé sur un accumulateur, une variable globale qui est initialisée à 0 au début du programme. Ceci est utilisé par presque tous les opérateurs de la langue. Seuls certains ne modifient pas la valeur de l'accumulateur.

Personnage sorti

a

Prend la valeur de l'accumulateur comme code ASCII et sort le caractère. Ne modifie pas la valeur de l'accumulateur.

Si l'accumulateur est supérieur à 255, le programme renverra une erreur. De même si l'accumulateur est inférieur à 0.

Numéroter

o

Sort la valeur de l'accumulateur. Ne modifie pas la valeur de l'accumulateur.

Augmenter

^

Augmentez l'accumulateur d'une unité.

Diminution

v

Diminuez l'accumulateur d'une unité.

Ajouter

+x

Définit l'accumulateur à la valeur de l'accumulateur plus la valeur de x.

Soustraire

-x

Définit l'accumulateur à la valeur de l'accumulateur moins la valeur de x.

Multiplier

*x

Définit l'accumulateur à la valeur de l'accumulateur multipliée par la valeur de x.

Diviser

/x

Définit l'accumulateur à la valeur de l'accumulateur divisée par la valeur de x. (Notez que c'est une division entière, donc cela 1/6donne 0)

Nombre

n

Réglez l'accumulateur sur l'entier n.

Remarque

Ici, xet npeut être n'importe quel entier de 0à 2^32-1inclusif.

Plus d'information

Vous ne devez utiliser que les opérateurs décrits ci-dessus. Par conséquent, votre programme Fourier généré n'est pas valide s'il utilise l'un des éléments suivants (notez que les opérateurs suivants sont autorisés pour la prime):

  • Répéter les boucles
  • Si les déclarations
  • Variables
  • au hasard
  • Modulo
  • Entrée utilisateur
  • Supérieur / inférieur aux opérateurs
  • Opérateurs d'égalité
  • Écran propre
  • Temporisation
  • Fonctions de date

Votre programme peut être un programme complet ou une fonction, prenant en entrée via STDIN, un fichier ou des arguments de fonction. Vous pouvez également saisir des informations directement depuis Internet.

Notez que s'il y a un vvdans votre code, vous devez le remplacer par -2. Il en va de même pour le ^^remplacer par +2.

Exemples

Si l'entrée est 7n, alors le programme attendu est:

55a110a

Mais vous pouvez enregistrer un octet avec

55a*2a

Une autre façon est

7o110a

Utilisation du numéro.


De même, si l'entrée est Hello, alors le programme attendu est:

72a101a108a108a111a

Vous pouvez jouer au golf de 3 octets (car la sortie ne change pas l'accumulateur):

72a101a108aa111a

Mais attendez, nous pouvons utiliser l'opérateur d'addition, économisant 2 octets:

72a101a+7aa+3a

Formatage

Parce que je vais utiliser le classement Stack Snippet de Martin Büttner, veuillez formater le titre comme suit:

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

Ensuite, vous pouvez mettre tout ce que vous souhaitez sous le titre.

Gagnant

Vous devez publier la longueur des programmes Fourier (produits par votre code) pour sortir ce fichier texte et ce fichier texte . Votre score est la longueur combinée des deux programmes Fourier en octets (les caractères non ASCII ne sont pas utilisés dans Fourier, donc cela ne fait pas vraiment de différence).

La personne avec les scores les plus bas gagne. S'il y a égalité, le programme le plus court en octets l'emporte.

Prime

Cette prime de 500 répétitions est pour une nouvelle réponse qui joue les cordes en utilisant l'une des fonctions de Fourier. Cela inclut les variables, les boucles et les instructions if, etc. Cette nouvelle réponse ne sera pas acceptée.

Classement

Reportez-vous à la section de mise en forme ci-dessus:

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>

Beta Decay
la source
6
Je ne pense pas que devoir produire toutes les solutions optimales soit très juste / intéressant. Il exclut toutes les implémentations sauf la force brute ...
orlp
5
Le vrai problème d'avoir à produire toutes les solutions optimales est que pour une entrée longue, il y aura plus de solutions optimales qu'il y a d'atomes dans l'univers.
isaacg
1
@orlp Edited out produisant toutes les solutions optimales
Beta Decay
1
Doit-il seulement être ASCII imprimable, ou toute sorte d'ASCII? Et seulement ASCII 7 bits, ou octets complets?
orlp
1
L'accumulateur démarre-t-il à 0?
ASCIIThenANSI

Réponses:

9

Python, 14307118 octets

601216 pour Hamlet + 13705902 pour Genesis = 14307118

Il y a certainement certains sénarios dans lesquels cette solution n'est pas optimale, comme pour 1111, où elle sortira 1111opar opposition à 11oo. Cependant, je pense que c'est presque optimal.

Modifier: enregistré quelques octets en améliorant 0o0oà 0oo.

Le nom du fichier contenant l'entrée est reçu sur STDIN, sorti sur STDOUT.

Résultats vérifiés avec l'interprète officiel.

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
la source
@Shebang Eh bien, je suis presque sûr que le résultat de Geobit est faux, voir mes commentaires là-bas.
isaacg
Il y avait très peu dedans, mais vous avez gagné avec seulement 5 caractères (vous et Razvan à égalité donc j'ai utilisé votre longueur de code comme bris d'égalité)
Beta Decay
2
@BetaDecay Je n'ai jamais vu le bris d'égalité de longueur être pertinent entre une paire de programmes non golfés auparavant.
isaacg
Ouais ... Moi non plus: P
Beta Decay
13

> <>, 14310665 octets

601398 pour hameau + 13709267 pour genesis

C'est toujours un travail en cours et prend beaucoup de temps à terminer.

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
la source
C'est fou petit, dommage que ce ne soit pas optimal cependant.
orlp
Je travaille sur l'utilisation de /, * et o, mais cela commence à prendre plus de place.
Aaron
18
Ça va, les poissons grandissent normalement à chaque récit de l'histoire;)
Geobits
Eh bien, c'est un brillant choix de langue: D
Beta Decay
Votre programme ne correspondait pas aux critères de la prime (aucune des réponses publiées ne l’a été), je vous l’ai donc attribuée parce que j’aime que vous ayez utilisé <> <.
Beta Decay
8

Java, 14307140 octets

Hameau - 601218

Genèse - 13 705 922

L'idée ici est de faire tout le travail à l'avance, en faisant une carte de caractère-> caractère. Ensuite, vous pouvez simplement parcourir et saisir les chaînes les plus courtes.

Une petite exception doit être faite pour les chiffres, donc je les vérifie dans la boucle principale. Il est toujours rapide, cependant, et gère le plus grand cas de test en quelques secondes. Je peux peut- être modifier cette section pour quelques octets de plus, mais je suis presque sûr qu'elle est presque optimale.

L'entrée est un nom de fichier comme argument. La sortie est écrite dans un fichier inputFilename_out.4et le nombre de caractères est envoyé à STDOUT.

Ceci est 1737 octets pour le bris d'égalité, complètement non golfé. Je peux beaucoup jouer au golf si nécessaire, mais ça va quand même être un peu gros.

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

}
Géobits
la source
Je pense que cela ne gère pas correctement les chaînes de chiffres avec des zéros non significatifs. Par exemple, sur l'entrée 01, je crois qu'il sort 01o, ce qui n'est pas correct.
isaacg
De plus, je pense que vous abusez de l'accumulateur. Dans la elseclause de la boucle principale, vous choisissez entre utiliser la valeur réelle de l'accumulateur et la valeur de caractère du caractère précédent. Vous ne pouvez pas faire ce dernier choix si les deux sont différents, car cela signifie que vous avez utilisé ole temps précédent et que l'accumulateur ne contient pas la valeur du caractère précédent.
isaacg
Bon, les deux devraient être corrigés maintenant. Merci!
Geobits
Lorsque je lance ceci sur ma machinge, j'obtiens 625474 pour Hamlet et 13705922 pour Genesis.
isaacg
@isaacg Le lancez-vous sur le même fichier (avec les mêmes fins de ligne)? J'ai rencontré un problème avec les fins de ligne plus tôt. Lorsque je lance le mien et le vôtre sur le même fichier, ils affichent tous les deux les scores affichés.
Geobits
2

PHP, 14307118 octets

601216 (Hameau) + 13705902 (Bible)

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

Sortie Fourier pour Hamlet

Cela fonctionne comme suit:

  1. Itère sur chaque caractère de l'entrée;
  2. S'il y a une séquence de chiffres de début non 0, il définira l'accumulateur sur ce nombre et le sortira sous forme de nombre. Il vérifie également les chiffres similaires;
  3. Sinon, vérifie s'il existe un moyen plus court de sortir le caractère actuel (plutôt que le code ASCII + symbole "a" = 4 caractères) en effectuant une opération de base (+ - * /) sur l'accumulateur avec un nombre compris entre 2 et 9; évidemment, il essaie aussi de comparer / incrémenter / décrémenter;
Razvan
la source