45

4

In this challenge, you will receive an input, convert it to hexadecimal, make a couple changes, and output the result.

Because they are only 16 characters in hexadecimal, your code will need to be as short as possible.

## Examples

Examples are separated by a blank line. First line is input, second line shows the steps, third shows the output

234589
234589 -> 3945D -> 39454 -> 9A1E -> 9115 -> 239B -> 2392 -> 958
958

435234
435234 -> 6A422 -> 61422 -> EFEE -> 5655 -> 1617
1617

153
153 -> 99 -> 99 -> 63
1617


## Steps

The input will always be a positive integer

In order to generate the output you will follow the following steps:

1. Convert the input to hexadecimal
2. Replace any letters with their index in the alphabet (e.g. a -> 1, b -> 2)
3. Convert the result back to hexadecimal
4. If the result contains any letters, go to step 2. If not, output the result

This is so shortest code in bytes wins!

27+1 for the justification "Because they are only 16 characters in hexadecimal, your code will need to be as short as possible." – cat – 2015-12-19T18:29:33.663

1A test case that passes through a zero digit (which is an important edge case for my current approach): 749699 -> B7083 -> 27083 -> 69CB -> 6932 -> 1B14 -> 1214 -> 4BE -> 425 -> 1A9 -> 119 -> 77 – Martin Ender – 2015-12-19T18:53:16.757

5Test case 153. Step 1 > 99, Step 2 --> 99, Step 3 --> 63, output 63. Correct? – edc65 – 2015-12-21T12:09:24.477

Yes for 153 I had not seen the code Flow explanation... – RosLuP – 2019-01-30T09:51:21.057

For what it's worth... 3 out of the top 4 answers return 99 on input 153 and Dennis's seg-faults on the current version of Jelly. I'm going to quit testing while I'm ahead :) Are we sure that example is correct? – dana – 2019-01-31T04:31:41.803

13

# Jelly, 18 bytes

b⁴µ:⁵©+¹%⁵ḅ⁵ß¹®S¤?


Try it online!

The binary, 18 byte version of the source code has the xxd dump

0000000: 62 b6 8c 3a b7 85 2b 8e 25 b7 a3 b7 95 8e 88 53 83 3f b..:..+.%......S.?


and works with this version of the Jelly interpreter.

### How it works

b⁴µ:⁵©+¹%⁵ḅ⁵ß¹®S¤?  Define the main link -- Left input: a (number)

b⁴                  Convert from integer to base 16.
:⁵               Divide all base 16 digits by 10.
©              Save the result in a register.
+¹            Add the quotients to the base 16 digits.
%⁵          Take all resulting sums modulo 10.
ḅ⁵        Convert from base 10 to integer.
®S¤   Take the sum of the quotients from the list in the register.
?  If the result is non-zero:
ß         Recursively call the main link.
¹        Else, apply the identity function.


Ḍ (decimal-to-integer) should have worked as a shorthand for ḅ⁵, but the latest version of Jelly at the time of this post had a bug that prevented me from using it.

3What....is.....that....? – J Atkin – 2015-12-19T18:52:35.010

1Which encoding does this use? It doesn't look like UTF-8, or ISO-8859 – Downgoat – 2015-12-19T18:56:49.270

2@Downgoat It isn't. Jelly uses its own, custom encoding. The source code can be provided either in UTF-8 or as a binary file. – Dennis – 2015-12-19T18:57:35.257

@Dennis: Please provide documentation of that encoding, and preferably, the language too. Perhaps write an esolangs wiki article on it? That will increase its visibility too :) – Timwi – 2015-12-19T19:20:11.967

@Timwi Documentation is work in progress. I haven't documented the encoding yet, since it is still changing with every commit. The same goes for pretty much all other features... – Dennis – 2015-12-19T19:22:11.660

@Timwi It's in this file: code = ''.join([char_table[i] for i in code])

– Dennis – 2015-12-19T19:25:35.587

@Dennis: Yes, found it now. I think you’re making it too easy for yourself. You just put a line in your parser so that it can theoretically read a binary format in which each character is one byte, but you didn’t actually write your program in it. You wrote it in a Unicode-enabled editor using Unicode characters. You did not post the binary file that is actually 18 bytes, and even if you did, it will become invalid with every new instruction you add to the language. – Timwi – 2015-12-19T19:29:27.980

@Timwi Re scoring, how is that different from every single APL answer on this site? Nobody actually uses the APL code page... The source code in the custom encoding is 0000000: 62 b6 8c 3a b7 85 2b 8e 25 b7 a3 b7 95 8e 88 53 83 3f b..:..+.%......S.? (xxd dump). It is only changing since the language is currently under development. The char table will be fixed later. – Dennis – 2015-12-19T19:32:01.453

@Dennis: APL has a fixed, published, known encoding. I didn’t say you can’t score one character per byte; I just think you should post the answer that is actually 18 bytes in order to claim 18 bytes, and if you want to change the encoding in your interpreter, then your answer should state which old version of the interpreter understands the encoding you used in the answer. – Timwi – 2015-12-19T19:38:10.560

2@Timwi Fair enough. I've added both to the post. – Dennis – 2015-12-19T19:44:05.240

2In the defense of Dennis: since Jelly uses less than 256 chars, one could trivially define a fork of Jelly that just uses ANSI chars. The only difference would be readability and ease of remembering what each function does. – Adám – 2015-12-20T12:58:23.343

Actual link make jelly interpreter to segfault... There would be in the text what jelly version and the link point to that version...or not use a link – RosLuP – 2019-01-30T09:38:48.577

8

# JavaScript ES6, 989267 64 bytes

Saved 3 bytes thanks to @Downgoat, 3 more thanks to @user81655

Found a much, much shorter version, ditching the loop for recursion:

h=x=>(y=x.toString(16))>(r=y.replace(/\D/g,z=>'0x'+z-9))?h(+r):r


Probably the most interesting part of this program is the replace function:

z=>     // Implicit: z = one of "a", "b", "c", "d", "e", "f"
'0x'+z  // Add '0x' to the beginning of z.
// If z == "a", this results in "0xa".
-9      // Subtract 9. JavaScript automatically coerces the string to a number,
// and because the prefix "0x" means "convert from hexadecimal",
// the "a" is converted to 10, which then becomes 1 because of the subtraction.


### Test snippet

(taken from here)

h=x=>(y=x.toString(16))>(r=y.replace(/\D/g,z=>'0x'+z-9))?h(+r):r
<!--                               Try the test suite below!                              --><strong id="bytecount" style="display:inline; font-size:32px; font-family:Helvetica"></strong><strong id="bytediff" style="display:inline; margin-left:10px; font-size:32px; font-family:Helvetica; color:lightgray"></strong><br><br><pre style="margin:0">Code:</pre><textarea id="textbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><pre style="margin:0">Input:</pre><textarea id="inputbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><button id="testbtn">Test!</button><button id="resetbtn">Reset</button><br><p><strong id="origheader" style="font-family:Helvetica; display:none">Original Code Output:</strong><p><div id="origoutput" style="margin-left:15px"></div><p><strong id="newheader" style="font-family:Helvetica; display:none">New Code Output:</strong><p><div id="newoutput" style="margin-left:15px"></div><script type="text/javascript" id="golfsnippet">var bytecount=document.getElementById("bytecount");var bytediff=document.getElementById("bytediff");var textbox=document.getElementById("textbox");var inputbox=document.getElementById("inputbox");var testbtn=document.getElementById("testbtn");var resetbtn=document.getElementById("resetbtn");var origheader=document.getElementById("origheader");var newheader=document.getElementById("newheader");var origoutput=document.getElementById("origoutput");var newoutput=document.getElementById("newoutput");inputbox.value="234589";textbox.style.width=inputbox.style.width=window.innerWidth-50+"px";var _originalCode=null;function getOriginalCode(){if(_originalCode!=null)return _originalCode;var allScripts=document.getElementsByTagName("script");for(var i=0;i<allScripts.length;i++){var script=allScripts[i];if(script.id!="golfsnippet"){originalCode=script.textContent.trim();return originalCode}}}function getNewCode(){return textbox.value.trim()}function getInput(){try{var inputText=inputbox.value.trim();var input=eval("["+inputText+"]");return input}catch(e){return null}}function setTextbox(s){textbox.value=s;onTextboxChange()}function setOutput(output,s){output.innerHTML=s}function addOutput(output,data){output.innerHTML+='<pre style="background-color:'+(data.type=="err"?"lightcoral":"lightgray")+'">'+escape(data.content)+"</pre>"}function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}function onTextboxChange(){var newLength=getByteCount(getNewCode());var oldLength=getByteCount(getOriginalCode());bytecount.innerHTML=newLength+" bytes";var diff=newLength-oldLength;if(diff>0){bytediff.innerHTML="(+"+diff+")";bytediff.style.color="lightcoral"}else if(diff<0){bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgreen"}else{bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgray"}}function onTestBtn(evt){origheader.style.display="inline";newheader.style.display="inline";setOutput(newoutput,"");setOutput(origoutput,"");var input=getInput();if(input===null){addOutput(origoutput,{type:"err",content:"Input is malformed. Using no input."});addOutput(newoutput,{type:"err",content:"Input is malformed. Using no input."});input=[]}doInterpret(getNewCode(),input,function(data){addOutput(newoutput,data)});doInterpret(getOriginalCode(),input,function(data){addOutput(origoutput,data)});evt.stopPropagation();return false}function onResetBtn(evt){setTextbox(getOriginalCode());origheader.style.display="none";newheader.style.display="none";setOutput(origoutput,"");setOutput(newoutput,"")}function escape(s){return s.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}window.alert=function(){};window.prompt=function(){};function doInterpret(code,input,cb){var workerCode=interpret.toString()+";function stdout(s){ self.postMessage( {'type': 'out', 'content': s} ); }"+" function stderr(s){ self.postMessage( {'type': 'err', 'content': s} ); }"+" function kill(){ self.close(); }"+" self.addEventListener('message', function(msg){ interpret(msg.data.code, msg.data.input); });";var interpreter=new Worker(URL.createObjectURL(new Blob([workerCode])));interpreter.addEventListener("message",function(msg){cb(msg.data)});interpreter.postMessage({"code":code,"input":input});setTimeout(function(){interpreter.terminate()},1E4)}setTimeout(function(){getOriginalCode();textbox.addEventListener("input",onTextboxChange);testbtn.addEventListener("click",onTestBtn);resetbtn.addEventListener("click",onResetBtn);setTextbox(getOriginalCode())},100);function interpret(code,input){window={};alert=function(s){stdout(s)};window.alert=alert;console.log=alert;prompt=function(s){if(input.length<1)stderr("not enough input");else{var nextInput=input[0];input=input.slice(1);return nextInput.toString()}};window.prompt=prompt;(function(){try{var evalResult=eval(code);if(typeof evalResult=="function"){var callResult=evalResult.apply(this,input);if(typeof callResult!="undefined")stdout(callResult)}}catch(e){stderr(e.message)}})()};</script>

It'll save a few bytes to use a function for .toString(16): x=>eval("for(x=(j=n=>n.toString(16))(x);/\\D/.test(x);)x=j(+x.replace(/\\D/g,z=>+('0x'+z)-9))"). It might also save a few bytes using recursion – Downgoat – 2015-12-19T20:00:52.473

@Downgoat Thanks! I'd tried a .replace on the string before evaluating it, but that turned out longer. – ETHproductions – 2015-12-19T20:07:40.780

Also remember you can make it an anonymous function, omitting h= – Conor O'Brien – 2015-12-19T22:16:47.163

@CᴏɴᴏʀO'Bʀɪᴇɴ Thanks for the suggestions, but that won't work, because it needs to call itself. – ETHproductions – 2015-12-19T22:33:41.897

Gah! Didn't see the recursion. I'm and idiot >_< – Conor O'Brien – 2015-12-19T22:34:32.847

I realize this is an old answer. It seems to return an in correct answer for input 153. Expected result is 63. My original solution had the same issue. – dana – 2019-01-31T04:22:46.290

6

## CJam, 21 19 bytes

r{siGb_{(9%)}%_@#}g


Test it here.

### Explanation

A very rare case of negative modulo results being helpful. :)

r       e# Read input.
{       e# While the condition on top of the stack is truthy...
s     e#   Convert to string. This is a no-op in the first iteration, but necessary
e#   on subsequent iterations.
i     e#   Convert to integer.
Gb    e#   Get base-16 digits.
_{    e#   Copy and map over the copy...
(   e#   Decrement.
9%  e#   Modulo 9. If the digit was originally in the range 0 to 9, it will remain
e#   unchanged because -1 % 9 == -1. If the digit was in 10 to 15, it will become
e#   0 to 5, respectively.
)   e#   Increment. Undoes the decrement for unchanged digits and fixes the letter
e#   digits because A corresponds to 1, not 0.
}%
_     e#   Duplicate result.
@#    e#   Pull up original digits and try to find them in the array. This will be zero,
e#   i.e. falsy, if they are equal and -1, i.e. truthy, if they are not.
}g


Looks like another might be failing for 153? It seems odd that 3 out of the top 4 answers would have the same issue? http://cjam.aditsu.net/#code=r%7BsiGb_%7B(9%25)%7D%25_%40%23%7Dg&input=153

– dana – 2019-01-31T04:27:36.497

4

# Ruby, 35 + 1 = 36

With command-line flag p, run

$_='%x'%$_
for(;
(s=$"{ // 2) replace letters with their index in the alphabet s.Aggregate(0,(a,c)=>10*a+c%48) // 3) Convert the result back to hexadecimal :x}" // 4) If the result contains any letters, go to step 2 ).Any(c=>c>57);); // If not, output the result return s; }  Following the algo in the end of question post, 153 has to result in 63 and not 99 as seems to me your function some time ago returned – RosLuP – 2019-01-30T12:56:40.617 1@RosLuP - Got it to work w/ that 153, although now my solution is much longer :) I will work on getting it smaller, but for now at least it is handling that case correctly. – dana – 2019-01-30T16:55:12.453 2 # Python, 118 105 bytes def f(n):h=hex(n)[2:];return h if h.isdigit()else f(int(''.join(map(lambda x:chr((ord(x)-47)%48+47),h))))  2 # PHP, 140126122114112 87 or 84 bytes (including -r) Not entirely sure about how the rules around this as this is my first codegolf attempt, but the code can be run with php -r without needing <? and ?> ### Code $b=readline();while($c!=$b)$b=preg_replace('/\D/e','ord($0)-96',$c=dechex($b));echo$c  ### Formatted $b=readline();
while($c!=$b){
$b=preg_replace('/\D/e','ord($0)-96',$c=dechex($b));
}
echo "$b\n";  ### Alternate Code (using argv instead of stdin) for($b=$argv[1];$c!=$b;)$b=preg_replace('/\D/e','ord($0)-96',$c=dechex($b));echo$b


### Formatted

for($b=$argv[1];$c!=$b;) {
$b=preg_replace('/\D/e','ord($0)-96',$c=dechex($b));
}
echo $b;  ### Notes Edit 1: I cut out a call to intval() to save 14 characters as PHP will happily treat numerical strings as numbers. Edit 2: I removed \n from the output that I forgot to remove after testing, and removed quote marks from the final echo to save a total of 4 characters. Edit 3: Removed the last call to intval() Edit 4: Saved 2 bytes by removing quote marks from the regex line Edit 5: Changed [a-f] to \D to save 3 characters, removed strval call from preg_replace for 8 more; added version that uses argv[] instead of STDIN, moved the loop terminator into the while statement(oops!) saving 11 more characters, and moved the dechex call into the subject part of preg_replace for another 3, making a total of 25; also added a non-stdin version as an alternate version that uses 3 less characters. Thanks for the help, @Blackhole Welcome on Code Golf! Since files without opening tags are valid PHP files, we always count the tags in PHP (or alternatively, we count the two bytes for the -r option). But a leading ; is always shorter than a leading ?>, so don't forget it. By the way, here is a shorter code: for($a=$argv[1];$b!=$a;)$a=preg_replace('#\D#e','ord($0)-96',$b=dechex($a));echo$b; (-29 bytes). – Blackhole – 2015-12-19T22:34:32.823

Input 153 should give 63, not 99. But -r is free. (see https://codegolf.meta.stackexchange.com/a/2428/55735)

– Titus – 2019-01-31T11:08:40.993

1

# Japt, 21 bytes

ìG
®+zA
eV ?U:ßVmuA ì


Try it online!

A significant improvement over the existing Japt answer. It doesn't handle the 153 -> 63 case proposed in a comment, but none of the other answers seem to either so I'll leave it unless the OP clarifies.

Output as a list of decimal digits, could be changed to outputting a decimal number for 1 byte

Explanation:

ìG               #Get a list of base-16 digits, each as a base-10 number
e.g. 234589 -> [3,9,4,5,13]

®+zA             #Increment the numbers greater than 10
e.g. [3,9,4,5,13] -> [3,9,4,5,14]

eV ?             #If the second step didn't change any digit:
U            # Output the digits from step 1
:           #Otherwise
ß          # Repeat the program with new input:
V         #  The result of step 2
muA      #  With each digit modulo 10
ì    #  Treated as a base-10 number


1

# APL(NARS) 104 chars, 208 bytes

f←{k←10⊥{⍵≤9:⍵⋄1+10∣⍵}¨q←{(16⍴⍨⌊1+16⍟⍵)⊤⍵}⍵⋄9≥⌈/q:k,0⋄k,1}
t←{⍵≤0:0⋄0=2⊃v←f⍵:↑f↑v⋄{k←f⍵⋄0=2⊃k:↑k⋄∇↑k}⍵}


test:

  t 153
63
t 0
0
t 234589
958
t 435234
1617
t ¯123
0


I don't know if it is ok... Possible it is not enough for the standard quality answer...

1

## Mathematica, 107 bytes

(b=FromDigits)@NestWhile[b[#/.Thread[10~Range~15->Range@6]]~a~16&,#~(a=IntegerDigits)~16,MemberQ[a_/;a>9]]&


Can't think of any more ways to golf this...

1

# Java, 201 bytes

String f(int a){String s=Long.toString(a,16);while(s.matches(".*[a-z].*")){char[]b=s.toCharArray();for(int i=0;i<b.length;i++)if(b[i]>96)b[i]-=48;s=Long.toString(new Long("".valueOf(b)),16);}return s;}


1

## Mathematica, 80 bytes

i=IntegerDigits;f=FromDigits;f[#~i~16//.l_/;Max@l>9:>f[If[#>9,#-9,#]&/@l]~i~16]&


This uses a neat trick for while-loops I learned from alephalpha. The //. is "apply this substitution rule as often as possible". Then we use a pattern, l_/;Max@l>9 which only matches if the hexadecimal digit list still contains digits greater than 9.

1

# Japt, 45 40 bytes

I=_nG -9}H=_=ZsG)f/\D/ ?H$($ÂZr"\\D"I):Z


Pretty pathetic for a golfing language, huh? There seems to be a lot of folks realizing during this challenge that their interpreters have bugs, and I am now included among them. This should be able to be done in 30 bytes or less, but a bug makes this impossible.

This creates a function H that can be called like so:

I=_nG -9}H=_=ZsG)f/\D/ ?H$($ÂZr"\\D"I):Z}
$H(234589)$


Alternatively, here is a full program, taking input from STDIN:

I=_nG -9}H=_=ZsG)f/\D/ ?H$($ÂZr"\\D"I):Z}H$(U  Try it online! 1 # GNU Sed (with eval extension), 44 : y/ABCDEF/123456/ s/^/printf %X /e /[A-F]/b  I wish sed would allow y/A-F/1-6/. But it doesn't. 1 # Python 3, 101 89 bytes Overall, this is quite similar to Boomerang's solution, but it takes a few different approaches to various aspects. def d(n):n=hex(int(n))[2:];return n.isdigit()and n or d(str([ord(c)%12for c in n])[1::3])  This is the expanded version of my original code: def d(n): n = int(n) # Interpret input as a decimal integer. n = hex(n)[2:] # Convert it to hex, stripping the '0x'. if n.isdigit(): # If every character is a digit... return n # ...we're done. else: # Otherwise... n = ''.join(c if c < ':' else # ...don't change digits (':' is after chr(ord(c - 48)) # '9'), but do change letters ('1' is 48 for c in n) # characters before 'a'). return d(n) # Then follow the process again.  11 bytes were shed thanks to @pacholik (replacing the innards of the join with a single operation that worked for both digits and letters). Another byte was trimmed by replacing the join with a string-slicing trick that hit me in a lightbulb moment (but which already exists in the Python golfing tips, albeit under a heading that specifies Python 2). The join can be shortened to str(ord(c)%12)for c in n. – pacholik – 2015-12-20T15:49:05.890 0 # Japt, 18 bytes Æ=ìG ®%9ª9Ãì)sGÃæÑ  Try it 0 # PHP, 71 bytes while($n++<2|$b-$a=&$argn)$a=strtr($b=dechex($a),abcdef,123456);echo$a;  Run as pipe with -nR or try it online. Yields a warning for some inputs in PHP 7.1 and later; replace - with != to fix. Yields another warning in PHP 7.2; put abcdef in quotes to fix. 0 ## Seriously, 42 bytes 1╤╝4ª╗,$1WX╛@¿╜@¡;╜@¿;)╛;(\(+%\$Mεj;)=YWX


Hex Dump:

31d1bc34a6bb2c24315758be40a8bd40ad3b60bd40
a83b29be3b285c282b2524604dee6a3b293d595758


Try it online

There has to be a shorter way than this, but this is what I got... (This is where I find myself wishing W actually popped, since it's shorter to put a ; right before the last one when you DON'T want it to than to put an X after EACH W. Here, having W` pop instead of peek would save three bytes.)