Échangez des morceaux avec leurs voisins


26

Description de la tâche

Étant donné un entier, permutez ses (2k – 1) -e et 2k -e bits de poids faible pour tous les entiers k> 0 . Il s'agit de la séquence A057300 dans l'OEIS.

(Le nombre est supposé avoir «une infinité de zéros non significatifs». En pratique, cela signifie simplement ajouter un seul bit de 0 à des nombres de longueur impaire.)

entrez la description de l'image ici

Il s'agit de , donc le code le plus court (en octets) l'emporte.

Cas de test

0 -> 0
1 -> 2
9 -> 6
85 -> 170
220 -> 236
1827 -> 2835
47525 -> 30298

5
Pouvons-nous supposer que le nombre correspond à un int pour des choses comme les décalages de bits?
xnor

1
@xnor: Je pense que c'est le consensus par défaut / communauté (sinon les réponses en C etc. seraient toujours fausses)? Si sûr! :)
Lynn

@Lynn: C nécessite unsigned char array_of_bytes[1024]de fonctionner comme vous le souhaitez (c'est-à-dire être un champ de bits avec 1024 * CHAR_BITentrées). J'imagine que la plupart des réponses prenant en charge des entrées de longueur arbitraire supposeraient CHAR_BITmême, car le décalage des bits entre les octets est lourd. Vous pouvez donc absolument imposer une prise ken charge jusqu'à une taille constante, comme 256 ou quelque chose de raisonnable pour AES, et les langues sans types entiers 256 bits devraient utiliser des boucles. Cela pourrait rendre les vecteurs SIMD à considérer pour une réponse asm x86: P
Peter Cordes

2
J'échange @Geobits avec Minibits
Optimizer

Réponses:


9

Gelée , 10 9 7 octets

b4d2UFḄ

Essayez-le en ligne! ou vérifiez tous les cas de test .

Comment ça marche

b4d2UFḄ  Main link. Argument: n (integer)

b4       Convert n to base 4.
  d2     Divmod each quaternary digit x by 2, yielding [x : 2, x % 2].
    U    Upend; reverse each pair, yielding [x % 2, x : 2].
     F   Flatten the 2D list of binary digits.
      Ḅ  Convert from binary to integer.

20

Python 2, 26 octets

lambda n:2*n-3*(4**n/3&n/2)

Astuces de bits!

Say na la forme ...ghfedcbaen binaire. Ensuite, nous pouvons le diviser en deux

n   = o + 2*e
n   = ...hgfedcba
o   = ...0g0e0c0a
2*e = ...h0f0d0b0

Ensuite, le résultat à commutation de bits speut être exprimé commes=2*o+e .

s   = 2*o + e
s   = ...ghefcdab
2*o = ...g0e0c0a0
e   = ...0h0f0d0b

Nous préférons calculer un seul eet o, donc nous exprimons o=n-2*eet substituons

s=2*(n-2*e)+e = 2*n-3*e

Donc, il reste maintenant à exprimer een termes de n. Le nombre M=4**n/3a la forme ...10101010101en binaire, qui sert de masque pour les chiffres impairs. L'exposant ns'assure que Mc'est assez long. Prendre le bit à bit andde n/2et cette valeur donne ecomme souhaité.

n/2     = ...hgfedcb
M       = ...1010101
n/2 & M = ...h0f0d0b = e

On peut plutôt exprimer een termes de o e=(n-o)/2, ce qui donne s=(n+o*3)/2, ce qui économise un octet grâce à une optimisation de xsot.

lambda n:n+(n&4**n/3)*3>>1

Grande explication et bonne astuce pour utiliser le masque une seule fois en soustrayant de n. Cependant, je préfère la convention de dénomination des bits "impairs" et "pairs" opposée. Le LSB est le bit 0, qui est pair (même s'il s'agit du premier bit). Dans la programmation SIMD, où les shuffles sélectionnent souvent des éléments avec un index, les index comptent à partir de 0, il est donc normal de considérer l'élément bas comme un élément pair. par exemple[ 3 2 1 0 ]
Peter Cordes

J'ai ajouté une réponse C en utilisant votre expression. Tous les crédits pour les économies d'octets par rapport à la réponse C de Digital Trauma sont dus à cela.
Peter Cordes

2
26:lambda n:n+(n&4**n/3)*3>>1
xsot

@PeterCordes Votre code C fonctionne pour moi avec gcc 4.8.3 et les paramètres par défaut. f(x){return x+((x&~0U/3)*3)>>1;}renvoie 1 pour l'entrée 2 .
Dennis

@ Dennis: Ouais, travaille pour moi en C, mon mauvais. J'étais en train de tester l'expression dans calc(aka apcalc), pas vraiment C. Je pensais que j'allais bien car je n'avais pas besoin de troncature à 32 bits ou de complément à deux. Je ne pensais pas que l'expression avait l'air correcte, alors j'étais prêt à croire mes mauvais tests. Mais de toute façon, j'ai besoin d'un meilleur REPL pour développer des bithacks. Aucune suggestion? (idéalement la ligne de commande Linux, comme bc -lou calc, mais en fait exposant int32_t/ uint32_tou quelque chose, pas une précision étendue.)
Peter Cordes

10

Fonction C, 38

Bit-twiddling:

f(x){return(x&~0U/3*2)/2+(x&~0U/3)*2;}

Ideone.


Ou pour le plaisir:

Fonction récursive C, 43

Selon la formule OEIS ,a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

f(x){return x>3?4*f(x/4)+f(x%4):x%3?3-x:x;}

ou

f(x){return x>3?4*f(x/4)+f(x%4):x%2*2+x/2;}

Ideone.


1
La transformation intelligente de l'expression de xnor réduit cela à 32 octets en C. Je l'ai posté comme une réponse distincte, car il s'agit d'une approche considérablement différente.
Peter Cordes

8

CJam, 16 14 13 octets

ri4b4e!2=f=4b

Testez-le ici.

Explication

ri  e# Read input and convert to integer.
4b  e# Get base-4 digits.
4e! e# Push all permutations of [0 1 2 3].
2=  e# Select the third one which happens to be [0 2 1 3].
f=  e# For each base-4 digit select the value at that position in the previous
    e# list, which swaps 1s and 2s.
4b  e# Convert back from base 4.

Cette astuce avec les permutations est très bonne!
Luis Mendo

7

Pyth, 9 octets

iXjQ4S2)4

Essayez-le dans le compilateur Pyth .

Comment ça marche

  jQ4      Convert the input (Q) to base 4.
 X   S2)   Translate [1, 2] to [2, 1].
i       4  COnvert from base 4 to integer.

5

JavaScript (ES6), 32 30 octets

(n,m=0x55555555)=>n*2&~m|n/2&m

Fonctionne uniquement jusqu'à 1073741823 en raison des limitations des entiers JavaScript. 38 36 octets fonctionne jusqu'à 4294967295:

(n,m=0x55555555)=>(n*2&~m|n/2&m)>>>0

Edit: sauvé 2 octets grâce à @ user81655.

51 octets fonctionne jusqu'à 4503599627370495:

n=>parseInt(n.toString(4).replace(/1|2/g,n=>3-n),4)

Pourrait n<<1être n*2?
user81655

@ user81655 Et je peux utiliser n/2aussi! Je ne sais pas pourquoi je n'y avais pas pensé auparavant.
Neil

Je n'ai jamais vu >>>... qu'est-ce que c'est?
Titus

@Titus C'est comme >>>mais ça fait un changement non signé. >>>0convertit essentiellement en un entier non signé 32 bits.
Neil

5

Fonction asm x86: 14 octets de code machine

version uint64_t: 24 octets

Convention d'appel SysV x86-64 ( xen edi), mais ce même code machine fonctionnera également en mode 32 bits. (Où le leadécodera comme lea eax, [edi + eax*2], ce qui donne des résultats identiques ).

0000000000000040 <onemask_even>:
  40:   89 f8                   mov    eax,edi
  42:   25 55 55 55 55          and    eax,0x55555555
  47:   29 c7                   sub    edi,eax
  49:   d1 ef                   shr    edi,1
  4b:   8d 04 47                lea    eax,[rdi+rax*2]
  4e:   c3                      ret    
4f: <end>

0x4f - 0x40 = 14 octets

C'est la sortie du compilateur qui utilise l'excellente idée de masquage unique de xnor dans le sens inverse. (Et terminologie opposée: le bit bas est le bit 0, ce qui est pair, pas impair.)

unsigned onemask_even(unsigned x) {
  unsigned emask = ~0U/3;
  unsigned e = (x & emask);
  return e*2 + ((x - e) >> 1);
}

Je n'ai trouvé aucune amélioration par rapport à ce que fait le compilateur. Je pourrais l'avoir écrit comme mov eax, 0x555.../ and eax, edi, mais c'est la même longueur.


La même fonction pour les entiers 64 bits prend 24 octets (voir le lien Godbolt). Je ne vois aucun moyen plus court que 10 octets movabs rax, 0x55...pour générer le masque dans un registre. (x86div instructions sont maladroites, donc la division non signée de tous les uns par 3 n'aide pas.)

J'ai trouvé une boucle pour générer le masque en rax, mais c'est 10 octets (exactement la même longueur que le mov imm64).

# since 0x55 has its low bit set, shifting it out the top of RAX will set CF
0000000000000000 <swap_bitpairs64>:
   0:   31 c0                   xor    eax,eax      ; old garbage in rax could end the loop early
0000000000000002 <swap_bitpairs64.loop>:
   2:   48 c1 e0 08             shl    rax,0x8
   6:   b0 55                   mov    al,0x55      ; set the low byte
   8:   73 f8                   jnc    2 <swap_bitpairs64.loop>  ; loop until CF is set
000000000000000a <swap_bitpairs64.rest_of_function_as_normal>:
 # 10 bytes, same as   mov  rax, 0x5555555555555555
 # rax = 0x5555...
   a:   48 21 f8                and    rax,rdi
   ...

Si nous savions qu'aucun des octets existants dans raxn'a leur bit faible défini, nous pourrions ignorer le xor, et ce serait long de 8 octets.

Une version précédente de cette réponse avait une boucle de 10 octets utilisant l' loopinsn, mais elle avait un temps d'exécution d' 0xFFFFFFFFFFFFFF08itérations dans le pire des cas , car je ne fais que définir cl.


5

Oasis , 17 octets (non concurrent)

n4÷axxn4÷xxe+3120

Essayez-le en ligne!

Oasis est un langage conçu par Adnan qui est spécialisé dans les séquences.

Actuellement, cette langue peut faire récursivité et forme fermée.

Nous utilisons cette formule: a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

Pour spécifier le cas de base est simple: le 3120à la fin signifie simplement cela a(0)=0, a(1)=2, a(2)=1, a(3)=3.

n4÷axxn4÷xxe+3120
                0  a(0) = 0
               2   a(1) = 2
              1    a(2) = 1
             3     a(3) = 3

n                  push n (input)
 4÷                integer-divide by 4
   a               a(n/4)
    xx             double twice; multiply by 4
                   now we have 4a(n/4)
      n            push n (input)
       4÷xx        integer-divide by 4 and then multiply by 4
                   since there is no modulo currently, n%4
                   is built as n-(n/4*4)
           e       we should have done a(n-(n/4*4)), but this
                   is a shortcut for a(n-x) where x is the top
                   of stack. Therefore, we now have a(n-n/4*4)
                   which is a(n%4).
            +      add.

4

MATL , 10 octets

BP2eP1ePXB

Essayez-le en ligne!

Version modifiée pour générer les premiers termes de la séquence ( OEIS A057300 ).

Explication

B     % Take input implicitly. Convert to binary array
P     % Flip
2e    % Convert to two-row 2D array, padding with a trailing zero if needed. 
      % Because of the previous flip, this really corresponds to a leading zero
P     % Flip each column. This corresponds to swapping the bits
1e    % Reshape into a row
P     % Flip, to undo the initial flipping
XB    % Convert from binary array to number. Display implicitly

3

zsh, 28 octets

<<<$[`tr 12 21<<<$[[#4]$1]`]

Prend l'entrée comme argument de ligne de commande, sort sur STDOUT.

Il n'est pas compatible Bash car il utilise la syntaxe de conversion de base spécifique à zsh.

                       $1     input (first command line argument)
                 $[      ]    arithmetic expansion
                   [#4]       output in base 4
              <<<             pass the result of this to...
      tr                      the `tr' command
         12 21                and replace 1s with 2s, 2s with 1s
     `                    `   evaluate the result...
   $[                      ]  in another arithmetic expansion, to convert back
                                to base 10
<<<                           output the result on STDOUT

3

Rétine, 70 octets

. +
$ *
+ `(1 +) \ 1
1 $
x1
1
^
X
r` (.) (.)
2 $ 1 $
1
X@
+ `@ x
X@@
X*(@*)
$ .1
0 $

Suite de tests. (Légèrement modifié.)

Eh bien, juste pour le plaisir: 7 octets

T`12`21

Prend la base-4 comme entrée et les sorties comme base-4.

Essayez-le en ligne!


4
Je suis en conflit. Je veux voter contre la moitié inférieure de votre réponse, mais contre la moitié supérieure.
Dennis

1
@ Dennis Maintenant, j'ai ces bits échangés.
Leaky Nun

3

05AB1E, 8 octets

4B12‡4ö

Merci à @Adnan pour -5 octets!

Utilise l'encodage CP-1252.

Essayez-le en ligne!

Explication:

4B       - Take input and convert to base 4.
  12Â    - Push 12 bifurcated.
     ‡   - Transliterate [1, 2] to [2, 1].
      4ö - Convert to base 10.

2
Bien, mais vous pouvez le remplacer 1 2‚2 1‚par 12Â8 octets.
Adnan

Bonne réponse! Voici une alternative à 8 octets:4в2‰íJJC
Kevin Cruijssen

3

C, 32 30 29 octets

f(x){return(x&~0U/3)*3+x>>1;}                // 30 bit version, see below

// less golfed:
f(x){return ((x & 0x55555555)*3 + x) >>1;}   //  >> is lower precedence than +

Algorithme copié à partir du commentaire de xsot sur la réponse Python de xnor . Au lieu de masquer dans les deux sens, masquez dans un sens et combinez.

Cela se compile au même format que la dernière version que j'ai testée , et cela fonctionne (pour x jusqu'à 0x3FFFFFFFet pour x au-dessus, tant que le bit 30 n'est pas défini, voir ci-dessous). Dans le code machine, c'est la même longueur que ma réponse asm existante.


La version ci-dessus efface toujours la partie haute du résultat . La meilleure version sûre est de 32 octets:

g(x){return 2*x-3*(x/2U&~0U/3);}   // safe 32bit version, works for all x

La version Python n'a pas ce problème, car python utilise des types entiers de précision arbitraire lorsque cela est nécessaire , au lieu de tronquer à une limite supérieure fixe.


@ Dennis: Argh, oui, merci. J'ai fait ce dernier changement après le test et j'ai raté la différence de sortie asm. Pas étonnant que je pensais que ça avait l'air mal; J'avais oublié que >>cette priorité était si faible. Je ne joue pas assez souvent au golf pour me rappeler exactement quelles sont les règles, car les avertissements du compilateur suggérant des parens dans des cas dangereux me sauvent dans le vrai code. : P
Peter Cordes

2
Vous pouvez supprimer cet espace en réorganisant les termes dans l'expression.
xsot

2

Javascript (ES6), 113 109 octets

4 octets enregistrés grâce à Upgoat

n=>+('0b'+/(..)+$/.exec('0'+n.toString`2`)[0].split``.reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])[0],2)

Comment ça marche

n=>+('0b'+                              //parse as binary literal
    /(..)+$/.exec('0'+n.toString`2`)[0] //convert to binary string with an even number of digits
        .split``                        //convert to array
        .reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])
                                        //swap all numbers
)

utiliser +('0b"+binary_string_here)au lieu de `parseInt (..., 2)
Downgoat

1

J, 20 octets

4#.0 2 1 3{~4#.^:_1]

Usage

>> f =: 4#.0 2 1 3{~4#.^:_1]
>> f 85
<< 170

>>est STDIN et <<STDOUT.

Non golfé

to_base   =: 4 #.^:_1 ]
transpose =: 0 2 1 3 {~ to_base
from_base =: 4 #. transpose

Trois fourchettes.

Sidenote

Dans l'interprète officiel, ^:_1peut être remplacé par inv, en économisant 1 octet.

Cependant, aucun des interprètes en ligne ne l'implémente.



1

INTERCAL , 60 octets

DOWRITEIN.1PLEASE.1<-!1~#21845'$.1~#43690DOREADOUT.1DOGIVEUP

Essayez-le en ligne!

Fonctionne pour les entiers 16 bits, avec les E / S effectuées dans le format le plus naturel pour INTERCAL: l'entrée est une série de chiffres décimaux énoncés dans l'un des plusieurs langages naturels ou construits, et la sortie est en "chiffres romains massacrés".

C'est l'un de ces rares défis où les opérateurs binaires d'INTERCAL peuvent en fait être utilisés de manière intuitive, car le repositionnement des bits est leur raison d'être. Select ( ~) prend les bits de son premier argument correspondant à ceux de son deuxième argument et les place à droite avec des zéros, et mingle ( $) entrelace les bits de ses arguments de telle sorte que les bits du premier argument soient plus significatifs. La solution la plus simple consiste donc à sélectionner les bits alternatifs les moins significatifs ( .1~#21845), à sélectionner les bits alternatifs les plus significatifs (.1~#43690) et les entrelacer dans l'ordre inverse. Heureusement pour le nombre d'octets, bien que les opérateurs INTERCAL n'aient pas de priorité définie (car l'objectif du langage est de ne pas avoir de précédents), il s'avère que le C-INTERCAL sur TIO ne nécessite pas beaucoup de regroupement pour cette expression particulière, ne coûtant qu'un octet depuis '.peut être abrégé !.

Avec prise en charge des entiers 32 bits:

INTERCAL , 67 octets

DOWRITEIN:1PLEASE:1<-':1~#0$#65535'$:1~#65535$#0DOREADOUT:1DOGIVEUP

Essayez-le en ligne!

INTERCAL ne permet pas les littéraux 32 bits, ce qui en fait un peu plus facile à lire, car cela signifie que les constantes magiques pour sélectionner les bits alternés doivent être construites en mélangeant deux littéraux 16 bits ensemble, où chacun est à zéro et l'autre tous. (En fait, même s'il y avait des littéraux 32 bits, cela serait encore plus court. #0$#65535Est de deux octets de moins #1431655765, et il en va de même pour l'autre.) Cela communique tout le processus de manière anormale pour INTERCAL.

Une approche alternative avec une utilisation maladroite de la surcharge d'opérande :

INTERCAL , 71 octets

DO:1<-:1/.2$.3PLEASEWRITEIN:2DO:1<-:2PLEASE:2<-.3$.2DOREADOUT:2DOGIVEUP

Essayez-le en ligne!

Cela supprime complètement la sélection en déclarant qu'il :1est .2mélangé avec .3, en définissant :1l'entrée, puis en sortant .3mélangé avec .2. Depuis a :1été surchargé en tant que .2$.3, DO :1 <- :2attribue des valeurs à.2 et .3telles qui :1acquièrent la valeur de :2, ce qui a pour résultat de .2contenir les bits alternatifs les plus significatifs :2et de .3contenir les bits alternatifs les moins significatifs. Ce serait la plus courte des deux solutions 32 bits de quatre octets si elle PLEASE WRITE IN :1pouvait être remplacée PLEASE WRITE IN :2 DO :1 <- :2par une surcharge :1, maisCALCULATINGs'avère nécessaire pour utiliser la surcharge. J'ai également l'impression qu'il pourrait y avoir un moyen plus court d'effectuer la surcharge elle-même que de démarrer le programme DO:1<-:1/.2$.3, mais comme il s'agit d'INTERCAL, j'ai également l'impression qu'il ne peut pas y en avoir.


0

Mathematica, 44 octets

Fold[3#+##&,#~IntegerDigits~4/.{1->2,2->1}]&

Même approche que ma réponse CJam: convertir en base-4, permuter 1 et 2, reconvertir. Il utilise également l'astuce d'alephalpha pour remplacer FromDigitspar une Foldopération de sauvegarde d'un octet.


0

En fait, 16 octets

4@¡"21""12"(t4@¿

Essayez-le en ligne!

Explication:

4@¡"21""12"(t4@¿
4@¡               base 4 representation of n
   "21""12"(t     translate (swap 1s and 2s)
             4@¿  base 4 to decimal

0

J, 22 octets

([:,_2|.\,&0)&.(|.@#:)

Approche alternative basée sur la manipulation de tableaux au lieu de l'astuce de base 4.

Usage

   f =: ([:,_2|.\,&0)&.(|.@#:)
   (,.f"0) 0 1 9 85 220 1827 47525
    0     0
    1     2
    9     6
   85   170
  220   236
 1827  2835
47525 30298

Explication

([:,_2|.\,&0)&.(|.@#:)  Input: n
                   #:   Get the value as a list of base 2 digits
                |.@     Reverse it
(           )&.         Apply to the list of base 2 digits
         ,&0            Append a zero to the end of the list
    _2  \               Split the list into nonoverlapping sublists of size 2
      |.                Reverse each sublist
 [:,                    Flatten the list of sublists into a list
             &.(    )   Apply the inverse of (reversed base 2 digits)
                        to convert back to a number and return it

0

REXX, 88 octets

n=x2b(d2x(arg(1)))
o=0
do while n>''
  parse var n a+1 b+1 n
  o=o||b||a
  end
say x2d(b2x(o))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.