Skip to main content
save 39 bytes and added more explanation
Source Link
CursorCoercer
  • 4.8k
  • 10
  • 20

Hexagony, 161161 122 bytes

?{10''d0=.{&1=10''2\}{{<{1&{=*{=&/........}u44.\4476'*0&}=..:1&'$/:!@...>105_03""-~+{&<..)"<>-":\$....=&={{/.00000|"=}{{&={*={&1d000000}24=<....|...\{=&={.+..>""'....(<>........}240504"-~{&137{:_1&':!@..~<>"._3724476'*0){.>}{}11744..=}&={=$/_"'\>{={<>(<\&1=/

Try it online!Try it online!

        ? . { 1 0 ' ' d 0
       = { & 12 =\ } { {} <
u 4 4
    { 1. &\ {4 =4 *7 {6 =' &* /0
     . .& .} .= . . .$ ./ .: ." .-
   + :{ 1= & ' : != @{ .{ ./ . >| 1"
  = 0} 5{ _{ 0& 3= "{ -* ~= { & < . .1
  ) " < > - " : \ $ . . . .d .
0 0 0 0 0 0 } { { } 2 4 = < . .
  .0 .5 |0 .4 ." .- \~ { = & = {1 .3 +7
   .{ .: >_ "1 "& ' .: .! .@ . ( < >.
    . . .~ .< .> ." . .) .{ .{ .{ _=
     3 7 2 4$ 4/ 7_ 6" ' * 0 {
      .\ > } { } 1 1 7 4 4=
       . .{ =< }> &( =< {\ {& {1
        . .= ./ . . . . .

My first go at a Hexagony program. I will return to this later to hopefully golf it down considerably. The precision is overkill and the layout is very lazy, so there shouldCould probably still be lots of bytes to save. For nowgolfed some, but I'm just quite happy thatto have gotten it worksto side length 7.

We take the input and keep a running count of how many digits long we think it is. We enter a loop. For each iteration, we square the input and double this running count (since squaring roughly doubles length). We then truncate the input to the first 7 digits, and add the number of digits we took off to our running count. Iterating 24 times gives us more than enough precision. We then take our predicted length, add a constant, multiply by a constant and print it out.

The agony

So how is this implemented exactly? I'll refer to the memory graph as it is labeled below. as well as the colored paths.

colored paths for reference memory after computing ln(2)

Note that I only use one instruction pointer for this program, which is probably not optimal. We begin on the blue path. This initializes some variables, putting the input in A, 10 in H, 100000000 in I, and 24 on L leaving the memory pointer in L. Then on to the main loop in green. The main loop first uses G and F to square A, then similarly uses E and K to double D. Moving the memory pointer to B, we then use the yellow path to redirect into a sub loop on the orange tiles. This sub loop uses B an C to divide A by 10, compare against I and increment D. Once the input is less than I, We use the red path to traverse back to the main loop, putting the memory pointer back on L and decrementing. L serves as the main loop counter. Once L is 0, we break out of the main loop and on to the purple track. The purple track uses C and J to do the final subtraction and multiplication on the output in D. The final output ends up in J

Visualizations done with hexagony.net.

Hexagony, 161 bytes

?{10''d0={&1=}{{<{1&{=*{=&/...........:1&':!@...>105_03"-~{&<..)"<>-":\$.....00000}{{}24=<....|...\{=&={.+..>""'....(<>..........._3724476'*0{.>}{}11744..=}&={{{

Try it online!

        ? { 1 0 ' ' d 0
       = { & 1 = } { { <
      { 1 & { = * { = & /
     . . . . . . . . . . .
    : 1 & ' : ! @ . . . > 1
   0 5 _ 0 3 " - ~ { & < . .
  ) " < > - " : \ $ . . . . .
 0 0 0 0 0 } { { } 2 4 = < . .
  . . | . . . \ { = & = { . +
   . . > " " ' . . . . ( < >
    . . . . . . . . . . . _
     3 7 2 4 4 7 6 ' * 0 {
      . > } { } 1 1 7 4 4
       . . = } & = { { {
        . . . . . . . .

My first go at a Hexagony program. I will return to this later to hopefully golf it down considerably. The precision is overkill and the layout is very lazy, so there should be lots of bytes to save. For now I'm just quite happy that it works.

We take the input and keep a running count of how many digits long we think it is. We enter a loop. For each iteration, we square the input and double this running count (since squaring roughly doubles length). We then truncate the input to the first 7 digits, and add the number of digits we took off to our running count. Iterating 24 times gives us more than enough precision. We then take our predicted length, add a constant, multiply by a constant and print it out.

Hexagony, 161 122 bytes

?.{10''2\}{}u44.\4476'*0&}=..$/:"-+{=&={{/.|"=}{{&={*={&1d000000}{{}240504"-~{&137{:_1&':!@..~<>".){{{=$/_"'\>{={<>(<\&1=/

Try it online!

       ? . { 1 0 ' '
      2 \ } { } u 4 4
     . \ 4 4 7 6 ' * 0
    & } = . . $ / : " -
   + { = & = { { / . | "
  = } { { & = { * = { & 1
 d 0 0 0 0 0 0 } { { } 2 4
  0 5 0 4 " - ~ { & 1 3 7
   { : _ 1 & ' : ! @ . .
    ~ < > " . ) { { { =
     $ / _ " ' \ > { =
      { < > ( < \ & 1
       = / . . . . .

My first go at a Hexagony program. Could probably still be golfed some, but I'm happy to have gotten it to side length 7.

We take the input and keep a running count of how many digits long we think it is. We enter a loop. For each iteration, we square the input and double this running count (since squaring roughly doubles length). We then truncate the input to the first 7 digits, and add the number of digits we took off to our running count. Iterating 24 times gives us more than enough precision. We then take our predicted length, add a constant, multiply by a constant and print it out.

The agony

So how is this implemented exactly? I'll refer to the memory graph as it is labeled below. as well as the colored paths.

colored paths for reference memory after computing ln(2)

Note that I only use one instruction pointer for this program, which is probably not optimal. We begin on the blue path. This initializes some variables, putting the input in A, 10 in H, 100000000 in I, and 24 on L leaving the memory pointer in L. Then on to the main loop in green. The main loop first uses G and F to square A, then similarly uses E and K to double D. Moving the memory pointer to B, we then use the yellow path to redirect into a sub loop on the orange tiles. This sub loop uses B an C to divide A by 10, compare against I and increment D. Once the input is less than I, We use the red path to traverse back to the main loop, putting the memory pointer back on L and decrementing. L serves as the main loop counter. Once L is 0, we break out of the main loop and on to the purple track. The purple track uses C and J to do the final subtraction and multiplication on the output in D. The final output ends up in J

Visualizations done with hexagony.net.

wording
Source Link
CursorCoercer
  • 4.8k
  • 10
  • 20

The algorithm used to approximate here is one I came up with myself. I'm sure something like it has been done before, but I'll go over how the constraints of Hexagony led me to this particular method. The first useful observation is that all logarithms are the same, at least up to a constant multiple. If you weren't awareThat is, \$\log_a(x)=\frac{\log_b(x)}{\log_b(a)}\$. This is nice because \$\log_{10}\$ is easier to work with when dealing with decimal representations. In fact, it's super easy. We can approxiamte the base ten logarithm just by taking the length of the decimal representation! Unfortunately, on the range \$[0.1, 100]\$ this give us 4 possible output values. Not quite good enough. We need a way to make our numbers longer, but longer in a very specific way. Firstly, as I mentioned earlier, we can't even enter \$0.1\$ into Hexagony, so we pad the lengths and get some necessary input precision by multiplying everything by \$10^7\$. Then, we use another simple logarithm observation: \$\log(x)=\frac{1}{n}\log(x^n)\$. Which is to say, up to another constant multiple (which was already necessary), we can take our input to any power before taking the logarithm. Great, so we just take the input to some super high power, take the length of the result and multiply it by something. But there's still a problem. While this idea technically works, it means that we'd be multiplying and measuring the length of numbers millions of digits long. I'd never be able to verify any test cases. We've successfully made our numbers longer, now we need to make them shorter. So we break the large exponent into steps, and at each step we truncate the input. By looking at how much we truncate each time we can give an approximation for how long we think it would have gotten if it didn't truncate. This approxiamtion becomes our logarithm. So, for the actual algorihtm:

The algorithm used to approximate here is one I came up with myself. I'm sure something like it has been done before, but I'll go over how the constraints of Hexagony led me to this particular method. The first useful observation is that all logarithms are the same, at least up to a constant multiple. If you weren't aware \$\log_a(x)=\frac{\log_b(x)}{\log_b(a)}\$. This is nice because \$\log_{10}\$ is easier to work with when dealing with decimal representations. In fact, it's super easy. We can approxiamte the base ten logarithm just by taking the length of the decimal representation! Unfortunately, on the range \$[0.1, 100]\$ this give us 4 possible output values. Not quite good enough. We need a way to make our numbers longer, but longer in a very specific way. Firstly, as I mentioned earlier, we can't even enter \$0.1\$ into Hexagony, so we pad the lengths and get some necessary input precision by multiplying everything by \$10^7\$. Then, we use another simple logarithm observation: \$\log(x)=\frac{1}{n}\log(x^n)\$. Which is to say, up to another constant multiple (which was already necessary), we can take our input to any power before taking the logarithm. Great, so we just take the input to some super high power, take the length of the result and multiply it by something. But there's still a problem. While this idea technically works, it means that we'd be multiplying and measuring the length of numbers millions of digits long. I'd never be able to verify any test cases. We've successfully made our numbers longer, now we need to make them shorter. So we break the large exponent into steps, and at each step we truncate the input. By looking at how much we truncate each time we can give an approximation for how long we think it would have gotten if it didn't truncate. This approxiamtion becomes our logarithm. So, for the actual algorihtm:

The algorithm used to approximate here is one I came up with myself. I'm sure something like it has been done before, but I'll go over how the constraints of Hexagony led me to this particular method. The first useful observation is that all logarithms are the same, at least up to a constant multiple. That is, \$\log_a(x)=\frac{\log_b(x)}{\log_b(a)}\$. This is nice because \$\log_{10}\$ is easier to work with when dealing with decimal representations. In fact, it's super easy. We can approxiamte the base ten logarithm just by taking the length of the decimal representation! Unfortunately, on the range \$[0.1, 100]\$ this give us 4 possible output values. Not quite good enough. We need a way to make our numbers longer, but longer in a very specific way. Firstly, as I mentioned earlier, we can't even enter \$0.1\$ into Hexagony, so we pad the lengths and get some necessary input precision by multiplying everything by \$10^7\$. Then, we use another simple logarithm observation: \$\log(x)=\frac{1}{n}\log(x^n)\$. Which is to say, up to another constant multiple (which was already necessary), we can take our input to any power before taking the logarithm. Great, so we just take the input to some super high power, take the length of the result and multiply it by something. But there's still a problem. While this idea technically works, it means that we'd be multiplying and measuring the length of numbers millions of digits long. I'd never be able to verify any test cases. We've successfully made our numbers longer, now we need to make them shorter. So we break the large exponent into steps, and at each step we truncate the input. By looking at how much we truncate each time we can give an approximation for how long we think it would have gotten if it didn't truncate. This approxiamtion becomes our logarithm. So, for the actual algorihtm:

added explanation of algorithm
Source Link
CursorCoercer
  • 4.8k
  • 10
  • 20

My first go at a Hexagony program. I will return to this later to both explain and hopefully golf it down considerably. The precision is overkill and the layout is very lazy, so there should be lots of bytes to save. For now I'm just quite happy that it works.

Since there are no floats in Hexagony, input and output are both fixed point \$\lfloor n\cdot10^7\rfloor\$.

The algorithm

(skip to the second paragraph if you don't care how I came up with it or why it works)

The algorithm used to approximate here is one I came up with myself. I'm sure something like it has been done before, but I'll go over how the constraints of Hexagony led me to this particular method. The first useful observation is that all logarithms are the same, at least up to a constant multiple. If you weren't aware \$\log_a(x)=\frac{\log_b(x)}{\log_b(a)}\$. This is nice because \$\log_{10}\$ is easier to work with when dealing with decimal representations. In fact, it's super easy. We can approxiamte the base ten logarithm just by taking the length of the decimal representation! Unfortunately, on the range \$[0.1, 100]\$ this give us 4 possible output values. Not quite good enough. We need a way to make our numbers longer, but longer in a very specific way. Firstly, as I mentioned earlier, we can't even enter \$0.1\$ into Hexagony, so we pad the lengths and get some necessary input precision by multiplying everything by \$10^7\$. Then, we use another simple logarithm observation: \$\log(x)=\frac{1}{n}\log(x^n)\$. Which is to say, up to another constant multiple (which was already necessary), we can take our input to any power before taking the logarithm. Great, so we just take the input to some super high power, take the length of the result and multiply it by something. But there's still a problem. While this idea technically works, it means that we'd be multiplying and measuring the length of numbers millions of digits long. I'd never be able to verify any test cases. We've successfully made our numbers longer, now we need to make them shorter. So we break the large exponent into steps, and at each step we truncate the input. By looking at how much we truncate each time we can give an approximation for how long we think it would have gotten if it didn't truncate. This approxiamtion becomes our logarithm. So, for the actual algorihtm:

We take the input and keep a running count of how many digits long we think it is. We enter a loop. For each iteration, we square the input and double this running count (since squaring roughly doubles length). We then truncate the input to the first 7 digits, and add the number of digits we took off to our running count. Iterating 24 times gives us more than enough precision. We then take our predicted length, add a constant, multiply by a constant and print it out.

My first go at a Hexagony program. I will return to this later to both explain and hopefully golf it down considerably. The precision is overkill and the layout is very lazy, so there should be lots of bytes to save. For now I'm just quite happy that it works.

Since there are no floats in Hexagony, input and output are both fixed point \$\lfloor n\cdot10^7\rfloor\$.

My first go at a Hexagony program. I will return to this later to hopefully golf it down considerably. The precision is overkill and the layout is very lazy, so there should be lots of bytes to save. For now I'm just quite happy that it works.

Since there are no floats in Hexagony, input and output are both fixed point \$\lfloor n\cdot10^7\rfloor\$.

The algorithm

(skip to the second paragraph if you don't care how I came up with it or why it works)

The algorithm used to approximate here is one I came up with myself. I'm sure something like it has been done before, but I'll go over how the constraints of Hexagony led me to this particular method. The first useful observation is that all logarithms are the same, at least up to a constant multiple. If you weren't aware \$\log_a(x)=\frac{\log_b(x)}{\log_b(a)}\$. This is nice because \$\log_{10}\$ is easier to work with when dealing with decimal representations. In fact, it's super easy. We can approxiamte the base ten logarithm just by taking the length of the decimal representation! Unfortunately, on the range \$[0.1, 100]\$ this give us 4 possible output values. Not quite good enough. We need a way to make our numbers longer, but longer in a very specific way. Firstly, as I mentioned earlier, we can't even enter \$0.1\$ into Hexagony, so we pad the lengths and get some necessary input precision by multiplying everything by \$10^7\$. Then, we use another simple logarithm observation: \$\log(x)=\frac{1}{n}\log(x^n)\$. Which is to say, up to another constant multiple (which was already necessary), we can take our input to any power before taking the logarithm. Great, so we just take the input to some super high power, take the length of the result and multiply it by something. But there's still a problem. While this idea technically works, it means that we'd be multiplying and measuring the length of numbers millions of digits long. I'd never be able to verify any test cases. We've successfully made our numbers longer, now we need to make them shorter. So we break the large exponent into steps, and at each step we truncate the input. By looking at how much we truncate each time we can give an approximation for how long we think it would have gotten if it didn't truncate. This approxiamtion becomes our logarithm. So, for the actual algorihtm:

We take the input and keep a running count of how many digits long we think it is. We enter a loop. For each iteration, we square the input and double this running count (since squaring roughly doubles length). We then truncate the input to the first 7 digits, and add the number of digits we took off to our running count. Iterating 24 times gives us more than enough precision. We then take our predicted length, add a constant, multiply by a constant and print it out.

Source Link
CursorCoercer
  • 4.8k
  • 10
  • 20
Loading