Générer la séquence d'horizon du temple

39

Considérez le processus suivant:

  1. Prenez un entier non négatif N.

    par exemple N = 571

  2. Exprimez-le en binaire sans zéros au début. (Zéro est la seule exception, devenir 0.)

    par exemple 571= 1000111011en binaire

  3. Séparez les exécutions consécutives de uns et de zéros dans cette représentation binaire.

    par exemple , 10001110111, 000, 111, 0,11

  4. Trier les pistes du plus long au plus court.

    par exemple 1, 000, 111, 0, 11000, 111, 11, 1,0

  5. Ecraser tous les chiffres dans chaque course avec alternance 1« s et 0» s, en commençant toujours avec 1« s.

    par exemple 000, 111, 11, 1, 0111, 000, 11, 0,1

  6. Concaténez le résultat pour obtenir un nouveau nombre binaire.

    par exemple 111, 000, 11, 0, 11110001101= 909en décimal

Lorsque vous tracez les valeurs produites par ce processus, vous obtenez un graphique très soigné:

Temple Skyline complot à 1024

Et j'espère comprendre pourquoi j'appelle la séquence résultante la séquence Temple Skyline :

Skyline du temple

Défi

Ecrivez un programme ou une fonction qui prend un entier non négatif N et imprime ou renvoie le numéro de séquence Temple Skyline correspondant. Votre entrée et votre sortie doivent être toutes les deux en décimales.

Par exemple, si l'entrée est 571la sortie doit être 909.

Le code le plus court en octets gagne.

Pour référence, voici les termes de la séquence de N = 0 à 20:

0   1
1   1
2   2
3   3
4   6
5   5
6   6
7   7
8   14
9   13
10  10
11  13
12  12
13  13
14  14
15  15
16  30
17  29
18  26
19  25
20  26

Voici les termes de 0 à 1023.

Les passe-temps de Calvin
la source

Réponses:

4

Pyth, 20 19 octets

ACr.BQ8|is*V_SGH2 1

1 octet enregistré par Jakube

Suite de tests

Utilise le fait qu'après l'encodage longueur-longueur, les exécutions sont les exécutions souhaitées dans la sortie.

Perdu 3 octets boîtier spécial 0.

isaacg
la source
14

CJam, 25 23 22 octets

ri1e>2be`z($W%a\+ze~2b

Juste un peu d'encodage de longueur. -1 merci à @ MartinBüttner.

Essayez-le en ligne / Suite de test .

Explication

ri        Read n from input as int
1e>       Take max with 1 (special case for n = 0)
2b        Convert n to binary
e`        Run length encode
z         Zip, giving a pair [<counts> <10101.. array>]
($W%      Drop the counts array and sort decending
a\+z      Add it back to the 10101.. array and re-zip
e~        Run length decode
2b        Convert from binary
Sp3000
la source
11

Pyth - 21 à 20 octets

Merci à @sok de m'avoir sauvé un octet!

is.em%hk2hb_Sr.BQ8 2

Essayez-le ici en ligne .

Maltysen
la source
Vous pouvez utiliser à la .BQplace de jQ2, ce qui signifie que vous pouvez perdre l’espace entre le 8et le précédent 2.
Sok
is*R`s=!Z_ShMr.BQ8 2est une solution intéressante de même longueur. Publier principalement parce que je ne m'attendais pas vraiment à ce que l'assignation dans un argument de carte fonctionne.
FryAmTheEggman
1
@FryAmTheEggman Remplacer `spar ]. Enregistre un octet.
Jakube
6

Python 2, 121 octets 125

121: Merci à Sp3000 d'avoir supprimé 4 octets!

import re;print int("".join(n*`~i%2`for i,n in enumerate(sorted(map(len,re.split('(1*|0+)',bin(input())[2:])))[::-1])),2)

125

import re;print int("".join("10"[i%2]*n for i,n in enumerate(sorted(map(len,re.split('(1*|0+)',bin(input())[2:])))[::-1])),2)
Enpenax
la source
1
Agréable! Je crois que vous pouvez aussi faire n*`~i%2`forau lieu de"10"[i%2]*n for
Sp3000
Merci pour l'édition! J'ai dû partir rapidement mais je voulais soumettre parce que je pensais que c'était un beau défi et un bon défi pour une première soumission. Je vérifierai votre soumission sous peu!
enpenax
Je pense que vous pouvez économiser des octets en utilisant sorted(...,key=len)au lieu d’utiliser map(len,...mais je ne comprends pas tout à fait votre programme pour le moment, donc je ne suis pas certain que cela vous serait bénéfique.
Cole
Hey @Cole, je mappe lenparce que c’est la seule information dont j’ai besoin pour reproduire le montant de 1 et 0. J’ai essayé votre suggestion et elle ajoute 2 octets, car je vais devoir l’utiliser lendeux fois, mais merci pour la suggestion!
enpenax
5

JavaScript ES6, 110 octets 113 116 119 120

3 octets sauvegardés grâce à @intrepidcoder

3 octets sauvés grâce à @NinjaBearMonkey

n=>+('0b'+n.toString(2).split(/(0+)/).sort((b,a)=>a.length-b.length).map((l,i)=>l.replace(/./g,i-1&1)).join``)

Approche directe. Je n'aime pas la longueur de la fonction de tri, mais je ne vois pas comment le jouer au golf.

Downgoat
la source
Je pense que vous pouvez utiliser un +au lieu de eval.
Intrepidcoder
@intrepidcoder merci, cela a sauvé 3 octets!
Downgoat
Je ne peux pas tester cela, mais je split(/(0+)/g)devrais pouvoir le remplacer match(/(.)\1*/g).
NinjaBearMonkey
@ NinjaBearMonkey merci, cela a sauvé 3 octets!
Downgoat
Sauver un octet: +(s=0, ... .map(l=>l.replace(/./g,s^=1))...)
J'espère pouvoir vous aider
5

C ++, 535 527 octets

(merci zereges d'avoir réduit quelques octets.)

Maintenant que nous nous sommes débarrassés de ces octets, le programme est maintenant compétitif;)

#include<iostream>
#include<cmath>
int main(){int I,D;std::cin>>I;while(I>int(pow(2,D))){D++;}int L[99];int X=0;int Z=0;int O=0;for(int i=D-1;i>=0;i--){if( int(pow(2,i))&I){if(Z>0){L[X]=Z;Z=0; X++;}O++;}else{if(O>0){L[X] = O;O=0;X++;}Z++;}}if(Z>0){L[X]=Z;Z=0;X++;}if(O>0){L[X]=O;O=0;X++;}int P=0;bool B = true;int W = D-1;for(int j=0;j<X;j++){int K=0;int mX=0;for(int i=0;i<X;i++){if(L[i]>K){K=L[i];mX=i;}}L[mX]=0;if(B){for(int k=0;k<K;k++){P+=int(pow(2,W));W--;}}else{for(int k=0;k<K;k++){W--;}}B^=1;}std::cout<<P;return 0;}

Je suis nouveau dans le golf, alors donnez-moi des conseils dans les commentaires .

Des choses comme "vous n'avez pas besoin de ces crochets" ou "utilisez printf" sont toutes utiles, mais j'apprécie également les conseils sur la logique. Merci d'avance!

Pour faciliter la lecture, je présente la version non-golfée:

#include<iostream>
#include<cmath>
int main()
{
int input,digits;

std::cin>>input;
while(input > int(pow(2,digits))){digits++;}

int list[99];
int index=0;
int zCounter=0;
int oCounter=0;

for(int i=digits;i>0;i--)
{
    if( int(pow(2,i-1))&input)
    {
        if(zCounter>0)
        {
            list[index] = zCounter;
            zCounter=0;
            index++;
        }
        oCounter++;
    }
    else
    {
        if(oCounter>0)
        {
            list[index] = oCounter;
            oCounter=0;
            index++;
        }
        zCounter++;
    }
}
if(zCounter>0)
{
        list[index] = zCounter;
        zCounter=0;
        index++;
}
if(oCounter>0)
{
        list[index] = oCounter;
        oCounter=0;
        index++;
}

int output = 0;
bool ones = true;
int power = digits-1;
for(int j=0;j<index;j++)
{
    int max=0;
    int mIndex=0;
    for(int i=0;i<index;i++)
    {
        if(list[i]>max){max=list[i];mIndex=i;}
    }
    list[mIndex]=0;

    if(ones)
    {
        for(int k=0;k<max;k++)
        {
            output+=int(pow(2,power));
            power--;
        }
    }
    else
    {
        for(int k=0;k<max;k++)
        {
            power--;
        }
    }
    ones^=1;

}
std::cout<<output;
return 0;
}

EDIT version golfée réduite de quelques octets, version non modifiée non modifiée

Liam
la source
Vous pouvez au lieu d' int a; int b;utiliser int a,b;. Les variables de la portée globale sont également initialisées avec 0. De plus, vous n'avez pas besoin d'utiliser des accolades lorsqu'il n'y a qu'une seule commande à exécuter. Aussi ones=!ones;peut être simplifié commeones ^= 1;
Zereges
Enregistré quelques octets merci
Liam
Déplacez votre première forboucle 1, c. for(int i=D;i;i--)-à- d. Et utilisez-la pow(2,i-1)à l'intérieur de la boucle.
nimi
@LiamNoronha Vous n'avez pas enregistré ce que j'avais recommandé :)
Zereges
1
@LiamNoronha Découvrez ceci . Il reste encore beaucoup à améliorer. Par exemple, la réutilisation de variables (enregistre la définition) onespeut également l'être int. Peut - être macroing int(pow(i))dans P(i). Je vous recommande de lire la discussion ici
Zereges
2

Haskell, 132 131 octets

import Data.List
g 0=[]
g n=mod n 2:g(div n 2)
q=[1]:[0]:q
f=foldl((+).(2*))0.concat.zipWith(<*)q.sortOn((-)0.length).group.g.max 1

Exemple d'utilisation:

> map f [0..20]
[1,1,2,3,6,5,6,7,14,13,10,13,12,13,14,15,30,29,26,25,26]

Comment ça marche:

                 max 1         -- fix n=0: f(0) is the same as f(1)
               g               -- turn into binary, i.e. list of 0s and 1s
            group              -- group sequences of equal elements
         sortOn((-)0.length)   -- sort groups on negative length
      zipWith(<*)q             -- map each element in a group to constant 1 or 0 by turns
   concat                      -- flatten all groups into a single list
foldl((+).(2*))0               -- convert back to decimal
nimi
la source
2

J - 30 octets

Fonction prenant un entier à droite. Gère correctement 0.

(\:~#2|#\)@(#;.1~1,2~:/\])&.#:
  • #: - Prenons la représentation binaire.
  • 1,2~:/\]- Entre chaque chiffre, indiquez Vrai s'ils sont différents. Préfixez un True afin que la liste ait True au début de chaque "exécution".
  • (#;.1~...) - En utilisant le vecteur booléen ci-dessus, prenez la longueur de chaque exécution.
  • \:~ - Triez ces longueurs du plus long au plus court.
  • 2|#\- Prenez une liste d'alterner 1 0 1 0 ...aussi longtemps que la liste de longueurs.
  • (...#...) - Pour chaque nombre à gauche (longueurs triées), prenez autant d'éléments de droite à droite (en alternant des 1 et des 0)
  • &. - Convertissez cette nouvelle représentation binaire en un nombre.

Exemples:

   (\:~#2|#\)@(#;.1~1,2~:/\])&.#: 571
909
   i.21   NB. zero to twenty
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   (\:~#2|#\)@(#;.1~1,2~:/\])&.#: every i.21   NB. apply separately to every number
1 1 2 3 6 5 6 7 14 13 10 13 12 13 14 15 30 29 26 25 26
algorithmeshark
la source
2

Perl 5.10, 121 101

say oct"0b".join'',map{$|=1-$|;$_=~s/./$|/gr}sort{length$b<=>length$a}(sprintf"%b",shift)=~/(0*|1*)/g

Je pense que la partie genre peut être plus courte.

Edit: -20 octets, grâce à symbabque!

Laposhasú Acsa
la source
Vous pouvez vous débarrasser de la \n, et la mn'est pas requise pour la correspondance d'expression régulière. Dans votre substitution, utilisez simplement à la .place du groupe char.
simbabque
Pas besoin de la greppartie non plus. Le octest soigné cependant :)
simbabque
Merci, j'ai accidentellement laissé ces parties du code original.
Laposhasú Acsa
1

Python 3, 146 136 octets

import re;print(int(''.join(len(j)*'01'[i%2<1]for i,j in enumerate(sorted(re.findall('1+|0+',bin(int(input()))[2:]),key=len)[::-1])),2))
Zach Gates
la source
Plutôt que mapd'un lambda, serait-il préférable de faire ''.join(... for ... in ...)?
Sp3000
1

Mathematica, 83 octets

Flatten[0#+(d=1-d)&/@SortBy[d=0;Split[#~IntegerDigits~2],-Length@#&]]~FromDigits~2&

Ceci définit une fonction non nommée.

Martin Ender
la source
0

Ruby, 107 104 102 octets

(sauvé 3 octets grâce à nimi )

Je ne vais pas battre CJam, mais je l'ai eu assez petit pour un langage sensé.

p gets.to_i.to_s(2).scan(/((.)\2*)/).map{|e|e[i=0].size}.sort.reverse.map{|e|"#{i=1-i}"*e}.join.to_i 2
Rétablir Monica iamnotmaynard
la source
Quelques octets à sauvegarder: (i+=1)%2is i=1-i.
nimi
@nimi Ah, merci. J'essayais de trouver un moyen de réduire cela.
Rétablir Monica iamnotmaynard
0

Java 8, 179 176 octets

(x)->{int g[]=new int[32],h=0,i=highestOneBit(x);g[0]=1;while(i>1)g[((x&i)>0)^((x&(i>>=1))>0)?++h:h]++;sort(g);for(i=32,h=0;g[--i]>0;)while(g[i]-->0)h=h<<1|i%2;return x<1?1:h;}

J'ai utilisé deux importations statiques: java.util.Integer.highestOneBitet java.util.Arrays.sort.

Pour plus de lisibilité, voici le code ungolfed:

java.util.function.ToIntFunction<Integer> f = (x) -> {
  int g[] = new int[32], h = 0, i = java.util.Integer.highestOneBit(x);
  g[0] = 1;
  while (i > 1) {
    g[((x & i) > 0) ^ ((x & (i >>= 1)) > 0) ? ++h : h]++;
  }
  java.util.Arrays.sort(g);
  for (i = 32, h = 0; g[--i] > 0;) {
    while (g[i]-- > 0) {
      h = h << 1 | i % 2;
    }
  }
  return x < 1 ? 1 : h; // handle zero
};
Olivier Grégoire
la source
-1

Python 2, 170 octets

def t(n):
  from itertools import groupby;lst=sorted([''.join(g) for n,g in groupby(bin(n)[2:])],key=len)[::-1];s=''
  for i in lst:s+=str(i)
  return int(s,2)
Tristan Batchler
la source
4
Bienvenue chez PPCG! Malheureusement, je pense que cela donne des valeurs incorrectes pour certains nombres, par exemple t(0) = 0quand 1est prévu et t(4) = 1quand 6 est attendu
Sp3000