Inscription / Connexion Nouveau Sujet
Niveau exercices
Partager :

reverse_bits

Posté par
iwan00
27-01-17 à 03:01

Bonjour!

je suis confronté à un petit probleme mathématique pour un défi que m'a proposé un copain en informatique, le défi est de faire un reverse_bits (je vais expliquer) en moins de 80 caracteres en C.
Le reverse bits consiste à inverser tout les bits (0 ou 1, c'est du binaire) d'une variable qui en possede 8,
exemple : 10001100 donnera 00110001 apres inversion.
pour réussir ce défi, je dois trouver la logique de cette suite, mais je bloque voici le début de la suite en transformant le binaire en décimal :
1   ->   128
2   ->   64
3   ->   192
4   ->   32
5   ->   160
6   ->   96
etc...
Si quelqu'un a une idée, je suis tout ouïe!

Posté par
luzak
re : reverse_bits 27-01-17 à 08:15

Bonjour !
As-tu entendu parler de l'opération XOR ?

Posté par
LittleFox
re : reverse_bits 27-01-17 à 12:31

Une solution simple (et qui peut donner un code court) est d'utiliser une seconde variable. On décale celle-ci vers la gauche en copiant le bit de poids faible de x tout en décalant x vers la droite :

#include <stdio.h>

char reverse_bits(char x) {
	char y;
	for(int i=0; i<8; i++){
		y=(y<<1)|(x&1);
		x>>=1;
	}
	return y;
}

int main(void) {
	int x;
	scanf("%d", &x);
	x = reverse_bits(x);
	printf("%d", x);
	return 0;
}


Le contenu de reverse_bits fait 79 caractères .

Il existe des solution plus rapides  mais pas nécessairement plus courtes à écrire :
- swap des bits i et 7-i ce qui peut être faite en leur appliquant un xor avec leur xor
- swap des bits pair et impairs puis swap des paires de bits puis swap des quadruplets de bits :

char reverse_bits(char x) {
	x=((170&x)>>1)|((85&x)<<1);
	x=((204&x)>>2)|((51&x)<<2);
	x=((240&x)>>4)|((15&x)<<4);
	return x;
}


Ce qui avec 102 caractères est un peu plus long.

Posté par
iwan00
re : reverse_bits 27-01-17 à 13:05

Merci pour cette réponse, malheureusement j'ai omis de dire plusieurs chose, je connaissais déjà ces solutions effectivement, elles sont assez efficace, mais je suis dans une école où on a une norme à respecter, par exemple des espaces entre les >> et les =, on a meme pas le droit d'utiliser for enfin bref, en fait mon post avait plutot un but mathématique, pas vraiment algorithmique.
Du coup ma vrai question était de savoir s'il existe un U tel que Un donne le reverse_bits n.

Posté par
carpediem
re : reverse_bits 27-01-17 à 18:08

salut

Citation :
Le reverse bits consiste à inverser tout les bits (0 ou 1, c'est du binaire) d'une variable qui en possede 8,
exemple : 10001100 donnera 00110001 apres inversion.
désolé mais je ne comprends pas cette "inversion" ...

1000 1100 ne devrait-il pas donner 0111 0011 ?

merci par avance

Posté par
carita
re : reverse_bits 27-01-17 à 18:14

bonjour,
j'ai eu la mm réflexion que vous !
mais ensuite j'ai fini par comprendre  : on voit comme dans un miroir, à l'envers.
le 1er chiffre en dernier, le second en avant-dernier, etc.

Posté par
verdurin
re : reverse_bits 27-01-17 à 18:18

Bonsoir,
je ne connais pas le C.

Mais une recherche simple donne l'opérateur adéquat : c'est ~

Posté par
carpediem
re : reverse_bits 27-01-17 à 18:21

ha le miroir ou palindrome ... ok merci !!

Posté par
iwan00
re : reverse_bits 27-01-17 à 18:58

comme je l'ai dis quelque poste plus haut, ce n'est pas de l'informatique, c'est des suites, le but est pas de trouver un algorithme mais de trouver la logique de la suite créer par le renversement binaire d'un nombre

Posté par
J-P Posteur d'énigmes
re : reverse_bits 27-01-17 à 19:43

Non verdurin, cela inverse chaque bit mais les laisse au même endroit.
Malheureusement, l'exemple sur le site que tu pointes est plus que malheureux, car il ne permet pas de distinguer les 2 sortes de transformations.

Principe possible (que je n'écris pas en C mais en utilisant les propriétés du C ):

Déclarer B comme byte
Déclarer A comme byte signé

B = 0
Entrer A (nombre à "inverser")

faire 8 boucles (par un for...)
{
  B devient (B + B)
  si A < 0
  {
    B devient B+1
  }
  A devient (A + A)
}
-----
Rappel :
En C, un nombre signé est considéré négatif si son bit de poids fort est 1
et en binaire, multiplier un nombre par 2, décale tous ses bits d'un rang vers la gauche.

Sauf distraction.  

Posté par
vham
re : reverse_bits 28-01-17 à 15:20

Bonjour,

@ J-P : Je ne comprends pas dans l'algorithme ci-avant car dans une des 8 itérations le bit 7 de A est introduit sur le bit 0 de B par le test "si A<0"
mais lors de l'itération suivante, ce bit est décalé vers la gauche par B+B
ainsi, après 8 itérations le B=0 devient le A initial.

Est-ce que j'ai mal interprété ?

Les exemples de Littlefox  27-01-17 à 12:31 avec & (ET), | (OU), >>, << fonctionnent bien
(alors que des ^ (XOR) seraient mal venus) grâce aux décalages dans les deux sens.


Citation :
iwan00 écrit :
ma vrai question était de savoir s'il existe un U tel que Un donne le reverse_bits n.

Si U et Un sont interprétés comme "réunions" (équivalent à un OU logique), il n'y a aucune chance d'aboutir sans décalage effectif de bits...

Posté par
J-P Posteur d'énigmes
re : reverse_bits 29-01-17 à 11:45

Dans mon algo, il y a un *2 au lieu d'un divisé par 2

En voici un autre écrit sur algobox.

VARIABLES
A EST_DU_TYPE NOMBRE
B EST_DU_TYPE NOMBRE
C EST_DU_TYPE NOMBRE
D EST_DU_TYPE NOMBRE
i EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE A
B PREND_LA_VALEUR 0
C PREND_LA_VALEUR 128
D PREND_LA_VALEUR 1
POUR i ALLANT_DE 1 A 8
DEBUT_POUR
SI (A >= C) ALORS
DEBUT_SI
B PREND_LA_VALEUR (B + D)
A PREND_LA_VALEUR (A-C)
FIN_SI
D PREND_LA_VALEUR 2*D
C PREND_LA_VALEUR C/2
FIN_POUR
AFFICHER B
FIN_ALGORITHME

Il est un peu différent de l'esprit du précédent, car je ne sais pas sous algobox limiter le nombre à un byte ...
Je n'ai plus d'émulateur en C .

Posté par
J-P Posteur d'énigmes
re : reverse_bits 29-01-17 à 11:47

Dans l'algo de mon message précédent, il faut bien entendu entrer un nambre A compris dans [0 ; 255] et en sortie B contient le nombre palyndrome (si on le retranscrit en binaire)

Posté par
vham
re : reverse_bits 29-01-17 à 19:09

Bonsoir,

L'opération reverse-bits demandée ne demande pas un "palindrome"
exemple : 10001100 donnera 00110001 apres inversion

Posté par
verdurin
re : reverse_bits 29-01-17 à 19:22

Pour la logique de la suite, on peut regarder ça récursivement.

Si on prend deux bits, il suffit de les échanger.
00
12
21
33

pour quatre bits on écrit les nombres en base 4, on échange les deux chiffres et on les transforme avec la table ci-dessus.
Par exemple (les bases sont en indices)
116=01410204=8
D16=31413234=B16
On obtient ainsi une table de correspondance pour les chiffres hexadécimaux.

Pour un octet on écrit le nombre en hexadécimal, on échange les deux chiffres et on utilise la table précédente pour les transformer.

Par exemple
100011002=8C16C83116=001100012

Posté par
J-P Posteur d'énigmes
re : reverse_bits 30-01-17 à 09:08

Citation :
L'opération reverse-bits demandée ne demande pas un "palindrome"


C'est juste.

L'algo que j'ai donné donne bien ce qui est attendu (qui n'est pas un palyndrome)

Par exemple en entrant A = 140 (soit donc en binaire 10001100)
l'algo en ressort 49  (soit  00110001 en binaire)

cela donne ceci :

reverse_bits

Posté par
mathafou Moderateur
re : reverse_bits 30-01-17 à 12:56

Bonjour,

le problème est que iwan00 semble rechercher l'impossible
une sorte de quête du Graal consistant à trouver une définition plus courte de l'opération "reverse-bits" que :

"échanger les bits de rangs i avec ceux de rangs 7-i"

HS : par ailleurs le palyndrome serait un néologisme concernant la course des grains de pollen ??

Posté par
jsvdb
re : reverse_bits 01-02-17 à 11:54

luzak @ 27-01-2017 à 08:15

As-tu entendu parler de l'opération XOR ?

Tu parles de cette série japonaise débile ?
ouiii ... jeee sais ... intervention particulièrement inutile ... bla bla bla ... sauf que là on est dans le rayon détente ...

Posté par
J-P Posteur d'énigmes
re : reverse_bits 01-02-17 à 17:17

Citation :
As-tu entendu parler de l'opération XOR ?


Oui, entré dans l'algo, cela donne ROX, le copain de Rouky

Posté par
LittleFox
re : reverse_bits 07-02-17 à 15:24


Citation :
un reverse_bits (je vais expliquer) en moins de 80 caracteres en C


Mais à part ça tu ne veux pas un algorithme mais une solution "mathématique", . Enfin, en voici une. J'espère qu'elle te plaira et qu'elles correspondront aux "normes de ton école à respecter" :

U^0_n = n, n \in \{0,1\}

U^{k+1}_n = 2^{2^k}U^k_{n \bmod 2^{2^k}} + U^k_{\left\lfloor\frac{n}{2^{2^k}}\right\rfloor}, 0 \le n < 2^{2^{k+1}}

La série que tu cherches est U^3_n.

Qui n'est que l'écriture mathématique de ce qui se cache derrière l'algorithme que j'avais donné plus haut :
Citation :
char reverse_bits(char x) {
	x=((170&x)>>1)|((85&x)<<1);
	x=((204&x)>>2)|((51&x)<<2);
	x=((240&x)>>4)|((15&x)<<4);
	return x;
}


Qu'on peut généraliser en (python):

def U(k,n) :
   if k == 0 :
      return n
   b = 2**(2**(k-1))
   return b*U(k-1,n%b) + U(k-1,n//b)

écrit plus efficacement :

def U(m,n):
 return U(m>>1,n&((1<<m)-1))<<m|U(m>>1,n>>m)if m else n

Avec m = 2^{k-1}, donc 4 dans notre cas. Le nombre de bits divisé par 2.
Tous cela écrit en 69 caractères .

Ce n'est pas très efficace, O(2m) alors que l'algorithme du haut est O(\log m).

Posté par
plumemeteore
re : reverse_bits 12-02-17 à 17:41

Bonjour.

Si la chaîne de caractères est vide, son inverse est une chaîne vide.
Sinon c'est l'inverse de la chaîne amputée de son premier élément, auquel on ajoute le premier élément.

Function reverse(n as str)
if n = "" then
reverse = "
else
reverse = reverse(mid(n, 2,len(n)-1)  & left(n,1)
EndFunction

En Lisp :
(De reverse (n)
(If (Not null (n)) (Cons (reverse(Cdr n)) (First n))) )



Vous devez être membre accéder à ce service...

Pas encore inscrit ?

1 compte par personne, multi-compte interdit !

Ou identifiez-vous :


Rester sur la page

Désolé, votre version d'Internet Explorer est plus que périmée ! Merci de le mettre à jour ou de télécharger Firefox ou Google Chrome pour utiliser le site. Votre ordinateur vous remerciera !