45
\$\begingroup\$

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!

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

23 Answers 23

13
\$\begingroup\$

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.
  µ                 Start a new, monadic link.
   :⁵               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.

\$\endgroup\$
12
  • 3
    \$\begingroup\$ What....is.....that....? \$\endgroup\$
    – J Atkin
    Dec 19, 2015 at 18:52
  • 1
    \$\begingroup\$ Which encoding does this use? It doesn't look like UTF-8, or ISO-8859 \$\endgroup\$
    – Downgoat
    Dec 19, 2015 at 18:56
  • 2
    \$\begingroup\$ @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. \$\endgroup\$
    – Dennis
    Dec 19, 2015 at 18:57
  • 2
    \$\begingroup\$ @Timwi Fair enough. I've added both to the post. \$\endgroup\$
    – Dennis
    Dec 19, 2015 at 19:44
  • 2
    \$\begingroup\$ 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. \$\endgroup\$
    – Adám
    Dec 20, 2015 at 12:58
8
\$\begingroup\$

JavaScript ES6, 98 92 67 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>

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

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
\$\endgroup\$
1
  • \$\begingroup\$ 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/… \$\endgroup\$
    – dana
    Jan 31, 2019 at 4:27
4
\$\begingroup\$

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 $_.

\$\endgroup\$
4
\$\begingroup\$

Julia, 78 74 bytes

f(x)=(h=hex(x);isdigit(h)?h:f(parse(replace(h,r"[a-z]",c->Int(c[1])-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[1]) - 96)))
    end
end
\$\endgroup\$
4
\$\begingroup\$

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

i`0:15YAt9X\t10ZQbb=~a]

Example

>> matl i`0: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        
\$\endgroup\$
2
  • \$\begingroup\$ You could write an answer in the old version of the language! \$\endgroup\$
    – lirtosiast
    Dec 19, 2015 at 23:43
  • \$\begingroup\$ @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 \$\endgroup\$
    – Luis Mendo
    Dec 20, 2015 at 3:05
3
\$\begingroup\$

Dyalog APL, 37 36 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.

\$\endgroup\$
3
  • \$\begingroup\$ -2 by choosing the right inequality functions: {∧/9≥X←16⊥⍣¯1⊢⍵:10⊥X⋄∇10⊥10|X+9<X} \$\endgroup\$
    – Adám
    Jan 29, 2019 at 7:20
  • 1
    \$\begingroup\$ or even shorter: 10⊥10|X+10≤X -> 10(⊣⊥|+≤)X (technically not equivalent, but works for hex digits) \$\endgroup\$
    – ngn
    Jan 29, 2019 at 16:01
  • 1
    \$\begingroup\$ 16⊥⍣¯1⊢⍵ -> ⍵⊤⍨⍴⍨16 \$\endgroup\$
    – ngn
    Jan 29, 2019 at 16:03
2
\$\begingroup\$

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))))
\$\endgroup\$
2
\$\begingroup\$

PHP, 140 126 122 114 112 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

\$\endgroup\$
2
  • \$\begingroup\$ 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). \$\endgroup\$
    – Blackhole
    Dec 19, 2015 at 22:34
  • \$\begingroup\$ Input 153 should give 63, not 99. But -r is free. (see codegolf.meta.stackexchange.com/a/2428/55735) \$\endgroup\$
    – Titus
    Jan 31, 2019 at 11:08
2
\$\begingroup\$

R, 106 103 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)
[1] "958"
> a(435234)
[1] "1617"
> a(99999)
[1] "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.

\$\endgroup\$
2
  • \$\begingroup\$ as.double is shorter than as.integer \$\endgroup\$
    – Giuseppe
    Aug 29, 2018 at 23:16
  • \$\begingroup\$ 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! \$\endgroup\$
    – Giuseppe
    Aug 29, 2018 at 23:20
2
\$\begingroup\$

05AB1E, 12 bytes

h[Au₂L‡hÐþQ#

Try it online or verify all test cases.

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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Feb 1, 2019 at 8:16
2
\$\begingroup\$

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;
}
\$\endgroup\$
2
  • \$\begingroup\$ 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 \$\endgroup\$
    – user58988
    Jan 30, 2019 at 12:56
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – dana
    Jan 30, 2019 at 16:55
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

Japt, 45 40 bytes

Based on my JS answer:

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!

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ The join can be shortened to str(ord(c)%12)for c in n. \$\endgroup\$
    – pacholik
    Dec 20, 2015 at 15:49
1
\$\begingroup\$

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;}
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

Japt, 18 bytes

Æ=ìG ®%9ª9Ãì)sGÃæÑ

Try it

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$

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.