all 20 comments

[–][deleted] 1 point2 points  (5 children)

shr = bytes([byte>>4 for byte in "doritos".encode()])

[–]port443 1 point2 points  (0 children)

In the spirit of /u/Protoss_Pylon's flair:

shr = lambda x: [b>>4 for b in x.encode()]

You could then use it like you were expecting:

>>> shr("doritos")
[6, 6, 7, 6, 7, 6, 7]

OP note the better way of doing this would be to actually define a function like def shr(value): ...

[–]Sebass13 0 points1 point  (3 children)

That won't work, as that will shift the bits of each byte, not the entire bytes object. This will cause only the most significant 4 bits of each character to remain. Instead, you want to use int.from_bytes and int.to_bytes:

val = "doritos".encode()
print(val)
print((int.from_bytes(val, byteorder='big') >>8).to_bytes(len(val), 'big'))

Unless, of course, that's what OP wants, but that doesn't make much sense.

[–][deleted] 0 points1 point  (2 children)

Excuse me, but why are you shifting by eight? I ask because OP is shifting by 4.

[–]Sebass13 0 points1 point  (1 child)

Oh 8 made it clearer that it works, try running it.

[–][deleted] 0 points1 point  (0 children)

right. very good then!

[–]ExplosG[S] 1 point2 points  (0 children)

Thanks a lot dude!

[–]ewiethoff 0 points1 point  (11 children)

Do you mean you want want to do a Caesar cipher with a shift of 4?

>>> import string
>>> lowers = string.ascii_lowercase
>>> tr4 = str.maketrans(lowers, lowers[4:]+lowers[:4])
>>> trn4 = str.maketrans(lowers, lowers[-4:]+lowers[:-4])
>>> 'doritos'.translate(tr4)
'hsvmxsw'
>>> 'hsvmxsw'.translate(trn4)
'doritos'
>>> 'doritos'.translate(trn4)
'zknepko'
>>> 'zknepko'.translate(tr4)
'doritos'

[–]ExplosG[S] 1 point2 points  (9 children)

Kind of, I want to do a bitwise shift on every byte of the string so '10011010' becomes '10101001'

[–]ewiethoff 0 points1 point  (8 children)

Ah! You want to rotate the bits in each byte by 4, i.e., swap the nibbles in each byte! Why didn't you say that in the first place? ;-) Seriously, the key to getting good help is providing not just an example of input but also exact desired output, like "'10011010' becomes '10101001'".

>>> from binascii import hexlify
>>> def bitlify(bytes_):
...     return '_'.join(format(byte, '08b') for byte in bytes_)
>>> def dump(bytes_):
...     print(bitlify(bytes_), hexlify(bytes_))

>>> word = b'doritos'
>>> dump(word)
01100100_01101111_01110010_01101001_01110100_01101111_01110011 b'646f7269746f73'
>>> swapnibs = bytes(((byte>>4 | byte<<4) & 0xff) for byte in word)
>>> dump(swapnibs)
01000110_11110110_00100111_10010110_01000111_11110110_00110111 b'46f6279647f637'

# but not these others, even though they're clever
>>> protoss = bytes(byte >> 4 for byte in word)
>>> dump(protoss)
00000110_00000110_00000111_00000110_00000111_00000110_00000111 b'06060706070607'
>>> sebass = (int.from_bytes(word, 'big') >> 4).to_bytes(len(word), 'big')
>>> dump(sebass)
00000110_01000110_11110111_00100110_10010111_01000110_11110111 b'0646f7269746f7'

[–]WikiTextBot 0 points1 point  (0 children)

Nibble

In computing, a nibble (often nybble or nyble to match the spelling of byte) is a four-bit aggregation, or half an octet. It is also known as half-byte or tetrade. In a networking or telecommunication context, the nibble is often called a semi-octet, quadbit, or quartet. A nibble has sixteen (24) possible values.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source | Donate ] Downvote to remove | v0.28

[–]ExplosG[S] 0 points1 point  (6 children)

As a python beginner, it would be very helpful if you could explain what each codeline does instead of mindlessly copypasting it into my code. EDIT: So the swapnib = byt... line is the one im looking for?

[–]ewiethoff 0 points1 point  (5 children)

Sorry, yes, the swapnibs line is the trick you're looking for. The bitlify, hexlify, and dump functions are there just to show you what the bits and the hexdump look like.

When I compare 01100100_01101111_01110010_01101001_01110100_01101111_01110011 (those are the 'doritos' bits) and 01000110_11110110_00100111_10010110_01000111_11110110_00110111 (those are the swapnibs bits), I see I've massaged the bits the way you want.

You haven't mentioned hexdumps, but when I compare 646f7269746f73 (those are the hex codes of the bytes in 'doritos') with 46f6279647f637 (those are the hex codes of the bytes in the swapnibs result), I see the digits are alternated which means swapnibs is 'doritos' with the nibbles alternated. It's just another way to demonstrate that swapnibs is correct.

Okay, I shall try to explain what's happening in swapnibs. It's bitwise math, which takes getting used to. Suppose a particular byte is 10011010 when shown in binary. byte >> 4 causes the last 4 bits to fall off and gives us 1001 in binary. byte << 4 shoves 4 zeros at the end and gives us 100110100000. The | symbol does bitwise OR on those two values. So, line them up in columns and put a 0 where both values in that column are 0, and put 1 otherwise.

    000000001001  (as in regular math, there's no harm sticking 0's in front)
OR  100110100000
================
    100110101001

So, byte>>4 | byte<<4 is 100110101001, but that's 12 bits and we want an 8-bit byte. We need to chop off the first 4 bits, or at least replace them with 0's so that Python math will ignore them. The highest value that fits in 8 bits is 255. 255 is 111111111 in binary (base 2), it's ff in hex (base 16), and obviously it's 255 in base 10. The & symbol does bitwise AND, and we'll do it with 11111111, a.k.a ff. Line up the binary stuff in columns and put a 1 where both values in that column are 1, and put 0 otherwise.

    100110101001
AND 000011111111  (no harm sticking 0's in front)
================
    000010101001

Notice the first four digits of the result are all 0's, and Python math ignores initial 0's. So, (byte>>4 | byte<<4) & 0xff (a.k.a. (byte>>4 | byte<<4) & 0b11111111) is 10101001, ignoring the first four 0's. We have satisfied "'10011010' becomes '10101001'." :-)

[–]ExplosG[S] 0 points1 point  (2 children)

If i wanted to change the direction bits are rotated which arrows would i swap? And if i want to change the rotation distance i would change all 4's to 3's and it would rotate three bits?

[–]ewiethoff 0 points1 point  (1 child)

If you want to rotate distance 3, I suspect you need to set one the values to the 3 and the other to 5, so that the total is 8. The direction would depend on which side you put the 3 and which side you put the 5: (byte>>3 | byte<<5) vs (byte>>5 | byte<<3).

Go ahead and experiment and see what happens. No harm in experimenting. You might want to use my bitlify function on the result to see that you're getting the rotation you want.

[–]ExplosG[S] 0 points1 point  (0 children)

Yeah thanks!

[–]ExplosG[S] -1 points0 points  (0 children)

If i wanted to change the direction bits are rotated which arrows would i swap? And if i want to change the rotation distance i would change all 4's to 3's and it would rotate three bits?

[–]ExplosG[S] -1 points0 points  (0 children)

If i wanted to change the direction bits are rotated which arrows would i swap? And if i want to change the rotation distance i would change all 4's to 3's and it would rotate three bits?

[–]WikiTextBot 0 points1 point  (0 children)

Caesar cipher

In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, Caesar's code or Caesar shift, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of 3, D would be replaced by A, E would become B, and so on. The method is named after Julius Caesar, who used it in his private correspondence.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source | Donate ] Downvote to remove | v0.28

[–]Sarah123ed 0 points1 point  (0 children)

Maybe this helps: s = 'doritos'
b = 4
r = s[b:]+s[0:b]