2
\$\begingroup\$

Inspired by "You had me at hello"

Introduction

For those who don't know, hexadecimal is a base system like decimal. Contrary to decimal however, it uses 16 (hence the name) digits instead of 10.

Here are the first few numbers while counting up in hexadecimal to maybe give you a feel of things, although you should probably google it for more info.

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20...

From now on I'll refer to hexadecimal as hex.


Challenge

Take a possibly infinite stream of bytes, and convert it to hex. This should be done as you read since you might get an infinite stream and keep on reading forever.

The twist, is that if a sequence of converted numbers equals the exact hex number DEADBEEF (3735928559 in decimal), you must output FEEDBEEF (4276993775 in decimal) instead.

If no DEADBEEF is found, print the string as it was

Inter-character matches work too, so 2D EA DB EE F0 works and should be converted to 2F EE DB EE F


Example

This might seem a bit vague, so here are 2 step-by-step examples.

Example 1

Input: Hello, World (bytes represented as string)

Step 1: Convert the input to ASCII: 072 101 108 108 111 044 032 087 111 114 108 100

Step 2: Convert the ASCII to hex: 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64

Step 3: Print out everything until DEADBEEF is found. It wasn't found, so just print Hello, World again.

Example 2

Input: Hello,Þ­¾ï,,

Step 1: Convert to ASCII: 72 101 108 108 111 44 222 173 190 239 44 44

Step 2: Convert to hex: 48 65 6C 6C 6F 2C DE AD BE EF 2C 2C

Step 3: Is there DEADBEEF? Yep. so take everything up to it. 48 65 6C 6C 6F 2C

Step 4: Append FEEDBEEF to it. 48 65 6C 6C 6F 2C FE ED BE EF

Step 5: Convert back to a string and print it. Output is Hello,þí¾ï


Scoring

Try to make a program that does the above in the fewest bytes of source code as possible.


Remember!

Make sure your program works for finite and infinite streams. The stream can be STDIN, file, function argument (if you can pass streams as arguments), or your language's closest alternative. Output is to STDOUT or function returning (if you can return streams).

More test cases (contain invisible characters)

eeþí¾Þ­¾ïe (6565feedbedeadbeef65) -> eeþí¾þí¾ïe
Þ­¾ï (deadbeef)-> þí¾ï
Þ=êÛîôV -> Þ?îÛîôV

\$\endgroup\$
6
  • 10
    \$\begingroup\$ "Take a ... stream of printable ASCII characters". Þ from your 2nd example isn't a printable ascii character. \$\endgroup\$
    – nimi
    Oct 30, 2018 at 23:19
  • 3
    \$\begingroup\$ @Rogem Printable ascii is a defined range of code points \$\endgroup\$
    – Jo King
    Oct 31, 2018 at 13:16
  • 2
    \$\begingroup\$ If an inter-match is found, like input -êÛîð (2D EA DB EE F0), do we convert it to 2F EE DB EE F0 (resulting in string -êÛîð) or 2F EE DB EE F (resulting in string -êÛî where the last character is the unprintable \x0f)? \$\endgroup\$ Oct 31, 2018 at 14:29
  • \$\begingroup\$ Your test cases should be either pasted as TIO links or as hex dumps if they contain unprintable characters. \$\endgroup\$
    – mbomb007
    Nov 1, 2018 at 21:28
  • \$\begingroup\$ @mbomb007 There are hexdumps of the inputs, the outputs don't contain unprintable characters \$\endgroup\$
    – kepe
    Nov 1, 2018 at 21:32

5 Answers 5

2
\$\begingroup\$

Python 3, 121 bytes

I=open(0).read
p=print
x=i=I(1)
while i:p(end=x[:-4]);x=x[-4:];x!='Þ­¾ï'or+p(end='þí¾ï');i=I(1);x+=i
p(end=x[:5])

Try it online!

\$\endgroup\$
4
  • 2
    \$\begingroup\$ or+p(end=...) causes a TypeError: bad operand type for unary +: 'NoneType' \$\endgroup\$
    – mypetlion
    Oct 30, 2018 at 23:02
  • \$\begingroup\$ A fixed version is here: tio.run/… \$\endgroup\$
    – Tyilo
    Oct 30, 2018 at 23:58
  • 2
    \$\begingroup\$ @mypetlion The error is on purpose, it crashes the program so that it stops outputting. \$\endgroup\$ Oct 31, 2018 at 12:47
  • \$\begingroup\$ Oh yes that does make sense. I might have misread the spec. \$\endgroup\$
    – mypetlion
    Oct 31, 2018 at 15:52
1
\$\begingroup\$

Japt, 34 30 bytes

-4 bytes from @Shagy

csG r`Ü%¼ef.+``fe‚¼ef` ò ®nG d

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ Added more test cases \$\endgroup\$
    – kepe
    Nov 1, 2018 at 17:34
  • 1
    \$\begingroup\$ 30 bytes using S.c() instead of S.m() and S.r() instead of S.s(). \$\endgroup\$
    – Shaggy
    Nov 1, 2018 at 17:49
  • \$\begingroup\$ @Shaggy Damn, I dont know how I didnt see those methods :o \$\endgroup\$ Nov 1, 2018 at 17:58
1
\$\begingroup\$

Clean, 143 bytes

uses octal escapes here and on TIO to prevent UTF-8 mangling, but it does work with the actual values and so each escape sequence is counted as one byte

This one works with inter-character sequences.

import StdEnv
$l=:[a,'\352\333\356',b:t]|(toInt a)rem 16==13&&(toInt b)>>4==15=[a+'\002':['\356\333\356\015']]=[hd l: $(tl l)]
$['\336\255\276\357':_]=['\376\355\276\357']
$[h:t]=[h: $t]
$e=e

Try it online!

Clean, 38 bytes

uses octal escapes here and on TIO to prevent UTF-8 mangling, but it does work with the actual values and so each escape sequence is counted as one byte

This one does not work with inter-character sequences.

$['\336\352\276\357':_]=['\376\355\276\357']
$[h:t]=[h: $t]
$e=e

Try it online!

Defines the function $ :: [Char] -> [Char] taking and returning a list of characters.
Since Clean is lazily-evaluated, this is equivalent to a stream.

\$\endgroup\$
4
  • \$\begingroup\$ Does it work with things like hex(0DEADBEEF9) \$\endgroup\$
    – kepe
    Nov 2, 2018 at 18:05
  • \$\begingroup\$ @FireCubez no, as that wasn't clearly required at the one I wrote this. I'll update it today so that it does. \$\endgroup\$
    – Οurous
    Nov 2, 2018 at 20:40
  • \$\begingroup\$ @FireCubez with interchacter matches, what is the second digit of the last F? Do we use 0x0F? 0xF0? \$\endgroup\$
    – Οurous
    Nov 3, 2018 at 0:23
  • \$\begingroup\$ @Ourous 0x0F would be used \$\endgroup\$
    – kepe
    Nov 3, 2018 at 0:31
0
\$\begingroup\$

05AB1E, 30 bytes

ÇhJl’–ìÀÜ’¡Dнsg1›’ŽåÀܒ׫2ôHçJ

Try it online or verify a few more test cases.

Explanation:

Ç                               # Convert the (implicit) input-string to codepoint decimals
 h                              # Convert them to hexadecimal
  J                             # Join them together
   l                            # Convert to lowercase
    ’–ìÀÜ’                      # Push compressed string "deadbeef"
          ¡                     # Split the hexadecimal string by this "deadbeef"
           D                    # Duplicate
            н                   # Take the first item of the split-list
             s                  # Swap so the full list is at the top of the stack again
              g1›               # Check if its length is larger than 1
                 ’ŽåÀܒ׫       # If it is: concat "feedbeef" to the head-string
                         2ô     # Split the string into parts of size 2
                           H    # Convert hexadecimal back to decimal
                            ç   # Decimal back to characters
                             J  # Join the characters (and output implicitly)

See this 05AB1E tips of mine (section How to use the dictionary?) to understand why ’–ìÀÜ’ is "deadbeef" and ’ŽåÀÜ’ is "feedbeef".

\$\endgroup\$
4
  • \$\begingroup\$ Why does it stop output when reaching a DEADBEEF? \$\endgroup\$
    – l4m2
    Nov 1, 2018 at 18:50
  • \$\begingroup\$ @l4m2 Because that is the challenge.. :) (I.e. in the second example, the two trailing ,, aren't output. It stops as soon as it found the DEADBEEF and appended the FEEDBEEF instead.) \$\endgroup\$ Nov 1, 2018 at 21:25
  • \$\begingroup\$ See. The question is inconsistant \$\endgroup\$
    – l4m2
    Nov 2, 2018 at 2:47
  • \$\begingroup\$ @l4m2 I agree. Although the other answers thus far (Python, Japt, and Clean) interpret it in the same way as me. \$\endgroup\$ Nov 2, 2018 at 7:26
0
\$\begingroup\$

C (gcc), 137 bytes

i=16;n;long long u;c;R(k){u=u<<4|c>>k&15,u^=u+'!RA'<<32?0:' @';}main(){for(;n+=!!~(c=getchar(n-=!i&&~putchar(u>>32)));i/=2)R(4),R(0);}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ @ceilingcat c is used in R, so can't move \$\endgroup\$
    – l4m2
    Nov 3, 2018 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.