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!

• +1 for the justification "Because they are only 16 characters in hexadecimal, your code will need to be as short as possible."
– cat
Dec 19, 2015 at 18:29
• A 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 Dec 19, 2015 at 18:53
• Test case 153. Step 1 > 99, Step 2 --> 99, Step 3 --> 63, output 63. Correct? Dec 21, 2015 at 12:09
• Yes for 153 I had not seen the code Flow explanation...
– user58988
Jan 30, 2019 at 9:51
• 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
Jan 31, 2019 at 4:31

# 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.

• What....is.....that....? Dec 19, 2015 at 18:52
• Which encoding does this use? It doesn't look like UTF-8, or ISO-8859 Dec 19, 2015 at 18:56
• @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. Dec 19, 2015 at 18:57
• @Timwi Fair enough. I've added both to the post. Dec 19, 2015 at 19:44
• In 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.
Dec 20, 2015 at 12:58

# 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;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 Dec 19, 2015 at 20:00
• @Downgoat Thanks! I'd tried a .replace on the string before evaluating it, but that turned out longer. Dec 19, 2015 at 20:07
• Also remember you can make it an anonymous function, omitting h= Dec 19, 2015 at 22:16
• @CᴏɴᴏʀO'Bʀɪᴇɴ Thanks for the suggestions, but that won't work, because it needs to call itself. Dec 19, 2015 at 22:33
• Gah! Didn't see the recursion. I'm and idiot >_< Dec 19, 2015 at 22:34

## 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? cjam.aditsu.net/…
– dana
Jan 31, 2019 at 4:27

# Ruby, 35 + 1 = 36

With command-line flag p, run

$_='%x'%$_
redo if$_.tr!'a-f','1-6'  Explanation: The -p flag creates a loop, storing the input and eventual output in the variable $_. '%x' does the hex conversion, and tr! does the digit substitution and returns a falsey value if there wasn't anything to change. redo starts over with the new $_. # Julia, 78 74 bytes f(x)=(h=hex(x);isdigit(h)?h:f(parse(replace(h,r"[a-z]",c->Int(c)-96))))  This is a recursive function that accepts an integer and returns a string. Ungolfed: function f(x::Integer) # Get the hexadecimal representation of x as a string h = hex(x) # Check whether all characters are digits if isdigit(h) # Return the hexadecimal representation of the input h else # Replace each letter with its position in the alphabet, # parse as an integer, and call f on the result f(parse(replace(h, r"[a-z]", c -> Int(c) - 96))) end end  # MATL, 23 25 bytes ### Disclaimer While writing this answer I noticed a bug in MATL's dec2base function, corrected it, and released a new version with the correction (as well as a couple other accumulated, unrelated changes). Since I am using a version which is later than this challenge, according to consensus on Meta this answer is not eligible for winning. ### Code i0:15YAt9X\t10ZQbb=~a]  ### Example >> matl i0:15YAt9X\t10ZQbb=~a] > 234589 958  ### Explanation i % input number  % do...while 0:15YA % convert number to representation with base defined by symbols 0,...,15 t9X\ % duplicate vector. Modulus 9 with 0 replaced by 9 t10ZQ % duplicate vector and convert to number using base 10 bb=~a % are second- and third-top stack elements different? (If so, next iteration) ] % end  • You could write an answer in the old version of the language! Dec 19, 2015 at 23:43 • @ThomasKwa The problem is that in the old version the compiler has a bug. I corrected it in the new version, which tangentially includes some (unrelated) new features Dec 20, 2015 at 3:05 # Dyalog APL, 3736 33 bytes {∧/9≥X←16⊥⍣¯1⊢⍵:10⊥X⋄∇10(⊣⊥|+≤)X}  Thanks to Adám and ngn for suggestions. I'm keeping 16⊥⍣¯1⊢⍵ instead of ⍵⊤⍨⍴⍨16 - it's an extra byte, but allows us to operate on numbers of arbitrary size rather than 64-bit. • -2 by choosing the right inequality functions: {∧/9≥X←16⊥⍣¯1⊢⍵:10⊥X⋄∇10⊥10|X+9<X} – Adám Jan 29, 2019 at 7:20 • or even shorter: 10⊥10|X+10≤X -> 10(⊣⊥|+≤)X (technically not equivalent, but works for hex digits) – ngn Jan 29, 2019 at 16:01 • 16⊥⍣¯1⊢⍵ -> ⍵⊤⍨⍴⍨16 – ngn Jan 29, 2019 at 16:03 # 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))))  # 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;$c!=$b;)$b=preg_replace('/\D/e','ord($0)-96',$c=dechex($b));echo$b


### Formatted

for($b=$argv;$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;$b!=$a;)$a=preg_replace('#\D#e','ord($0)-96',$b=dechex($a));echo$b; (-29 bytes). Dec 19, 2015 at 22:34
• Input 153 should give 63, not 99. But -r is free. (see codegolf.meta.stackexchange.com/a/2428/55735) Jan 31, 2019 at 11:08

# R, 106103 102 bytes

-3 bytes by using if instead of while

-1 byte thanks to Giuseppe using as.double instead of as.integer

a=function(y){x=as.hexmode(as.double(y))
if(grepl("[a-f]",x)){x=chartr("a-f","1-6",x);return(a(x))};x}


Try it online!

Just add a(your_integer_here) to the TIO to see the result.

> a(234589)
 "958"
> a(435234)
 "1617"
> a(99999)
 "4908"


I used recursion to reapply the function to each successive iteration, on the condition that it doesn't find any of the letters 'abcdef' within the string, when this condition is False, it outputs the result as a string. The best part was my discovery of the chartr function, which allows me to swap elements with corresponding elements in a string. This string comes from the function coercing the hexadecimal into a string format.

Edit: I tried to use sprint("%x",y) instead of as.hexmode(as.double(y)), but I am still required to use as.double somewhere in the code, which was 2 1 byte longer.

• as.double is shorter than as.integer Aug 29, 2018 at 23:16
• There are some more golfs to be done but I am on mobile at the moment. Feel free to join our R golfing chat and don't forget to check out (and contribute to) tips for golfing in R! Aug 29, 2018 at 23:20

# 05AB1E, 12 bytes

h[Au₂L‡hÐþQ#


Explanation:

h              # Convert the (implicit) integer-input to a hexadecimal string
#  i.e. 234589 → "3945D"
[             # Start an infinite loop:
Au           #  Push the uppercase alphabet "ABC...XYZ"
₂L         #  Push a list in the range [1,26]
‡        #  Transliterate: replace all letters with the integers at the same index
#   i.e. "3945D" → "39454"
#   i.e. "239B" → "2392"
h       #  Convert the integer to a hexadecimal string again
#   i.e. "39454" → "9A1E"
#   i.e. "2392" → "958"
Ð      #  Triplicate it
þ     #  Leave only the digits of the last copy
#   i.e. "9A1E" → "91"
#   i.e. "958" → "958"
Q    #  Check if these digits and the hexadecimal string are equal
#   i.e. "9A1E" and "91" → 0 (falsey)
#   i.e. "958" and "958" → 1 (truthy)
#   #  And if they are: stop the infinite loop
# (and output the remaining copy from the triplicate implicitly as result)


ÐþQ could alternatively be D.ï (D: Duplicate; .ï: is_int?) for the same byte-count.

• @MagicOctopusUrn [hÐþQ#Au₂L‡ doesn't always work unfortunately. The challenge states to convert to hex once first, and then in every iteration. If I paste your code in my test suite, the first three test cases are correct, but the last two fail. Feb 1, 2019 at 8:16

# C# (Visual C# Interactive Compiler), 92 bytes

n=>{var s=$"{n:x}";for(;(s=$"{s.Aggregate(0,(a,c)=>10*a+c%48):x}").Any(c=>c>57););return s;}


Try it online!

Less golfed code:

// anonymous function with
// input integer n
// output is a string
n=>{
// 1) Convert the input to hexadecimal
var s=$"{n: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
– user58988
Jan 30, 2019 at 12:56
• @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
Jan 30, 2019 at 16:55

## 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...

## 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.

# 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! # 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. # 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. Dec 20, 2015 at 15:49 # 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;}  # 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  # 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... ## 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.) # Japt, 18 bytes Æ=ìG ®%9ª9Ãì)sGÃæÑ  Try it # 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.