A double precision representation of a decimal can only guarantee an accuracy of 15 decimal places, thus pi is approximated as:
3.141592653589793
You can see that the digit 3
is in positions 1, 10, 16
, the digit 1
is in positions 2, 4
etc.
Challenge
Your task is to create a program or function that creates a random double number between 0 and 1, and maps the values of that number onto the value of pi. You do this by placing the different digits in the random numbers in the position that digit has in pi. If the digit is not found in pi, you'll skip it, and every digit in pi that's not in the random number will be represented by an x
. Each value can only be used once, starting from the left.
A few examples will probably make this more clear. In the following examples, the first number is pi, the second is the random number, and the last is the desired output.
3.141592653589793
0.111111111111111
x.1x1xxxxxxxxxxxx
3.141592653589793
0.531000000000000
3.1xx5xxxxxxxxxxx
3.141592653589793
0.123456789123456
3.141592653x8x7xx
3.141592653589793
0.967552381459391
3.14159265358979x
Rules:
- The function should not take any input (a possible exception is explained in bullet point 3)
- The output shall consist of only the output string, with an optional newline (a single trailing space is also accepted)
- If your program doesn't have a built-in Pi-value, and/or a RNG then you can hardcode Pi, and take the random number as input. You cannot hardcode the random number or take Pi as input.
- Both the hardcoded value for Pi, and the 15 random digits (you can skip
0.
since you know it will be between 0 and 1), will be included in the byte count. - If your language doesn't have the required precision, you can use less precision under the following restrictions
- The digits of Pi must be accurate up to the precision you have
- You can't output more values than you're guaranteed to have correct, i.e. you can't output 15 digits if the precision only allows 8 accurate decimals.
- The hardcoded value of Pi will count as 16 bytes (you don't need the decimal point), even if your program only supports 8 digits.
- The input value for the random number will count as 15 bytes (you don't need
0.
. This is because languages with low precision should not have an unfair advantage. - The program must support 5 decimals precision (at least).
- Edit: To validate the answer: The random number should be printed somehow, but this operation doesn't have to be included in the byte count. So for instance, if it's possible to insert a
print r
in the end of the script, that part will not increase the score. - You cannot subtract the bytes if it's part of another necessary operation. I.e. if the code is
print pi, r
, then you can only subtract, r
. - If you have to insert parts several places in the code, please include both versions (the one that prints the random number and the one that doesn't with a comment such as:
_p
and_oNo
are needed to print the random number._p
does xxx and_oNo
does yyy._p
and_oNo
will not be included in the byte count.
Shortest code in bytes win.
Leaderboard
The Stack Snippet at the bottom of this post generates the catalog from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
## Language Name, N bytes
where N
is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:
## Ruby, <s>104</s> <s>101</s> 96 bytes
If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:
## Perl, 43 + 2 (-p flag) = 45 bytes
You can also make the language name a link which will then show up in the snippet:
## [><>](http://esolangs.org/wiki/Fish), 121 bytes
var QUESTION_ID=67223,OVERRIDE_USER=44713;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>
9 Answers 9
LabVIEW, 53 LabVIEW Primitives
I match Strings and put the number into an "empty" x.xxx string and remove the number from pi so it doesn ́t show up again.
the random number and the single chars here are kinda visible, is that all right or do i have to redo the recording?
-
\$\begingroup\$ It's quite clearly doing the job even if a few chars are a bit hard to see, so you don't have to redo anything... Nice answer! =) \$\endgroup\$Stewie Griffin– Stewie Griffin2015年12月21日 16:27:16 +00:00Commented Dec 21, 2015 at 16:27
Mathematica, 105 or 147 characters
If random number "between 0 and 1" means 0 <= random <= 1
, i.e. includes 0 & 1.
StringReplace[ToString@InputForm@N@Pi,
Thread[ToString/@Complement[Range@9,RandomInteger[{0,9},15]]->"x"]]
(105 characters)
Otherwise, taking random number "between 0 and 1" to mean 0 < random < 1
.
Loop to get 15 random integers, not all zero. Select complement from 0 to 9 range, i.e. those numbers from 0 to 9 not in the random list. Convert those integers to strings and replace the matching characters in a pi string.
(147 characters)
While[True,r=RandomInteger[{0,9},15];
If[Union@r!={0},Break[]]];
StringReplace[ToString@InputForm@N@Pi,
Thread[ToString/@Complement[Range@9,r]->"x"]]
3.1x15x265358x7x3
Random digits:-
FromDigits[r]
820307536180783
-
\$\begingroup\$ Please include the version of the code you have actually counted. \$\endgroup\$Martin Ender– Martin Ender2015年12月21日 13:14:06 +00:00Commented Dec 21, 2015 at 13:14
-
\$\begingroup\$ Done. Line breaks only included for readability. \$\endgroup\$Chris Degnen– Chris Degnen2015年12月21日 13:35:05 +00:00Commented Dec 21, 2015 at 13:35
-
2\$\begingroup\$ Still comes out as 149 bytes for me (with linebreaks, 146 without). There's nothing wrong with adding both a golfed and an ungolfed version. Some golfing tips:
True
is1>0
,RandomInteger
can use infix notation{0,9}~RandomInteger~15
. You can probably save some bytes by givingr
some value and actually using the condition of theWhile
instead of usingBreak.
ThenFor
might save another byte overWhile
. Although I don't see why you need the loop at all if you instead assume the random number in range[0,1)
. \$\endgroup\$Martin Ender– Martin Ender2015年12月21日 13:42:09 +00:00Commented Dec 21, 2015 at 13:42 -
\$\begingroup\$ @MartinBüttner I like
1>0
:-) \$\endgroup\$Chris Degnen– Chris Degnen2015年12月21日 13:45:34 +00:00Commented Dec 21, 2015 at 13:45 -
\$\begingroup\$ I would usually read random number "between 0 and 1" to mean 0 < random < 1. \$\endgroup\$Chris Degnen– Chris Degnen2015年12月21日 13:46:43 +00:00Commented Dec 21, 2015 at 13:46
Pyth, 25 bytes
u&p?}HGH\x.-GH`.n0<`O017
Try it online: Demonstration or Test showing the random number
Explanation:
u&p?}HGH\x.-GH`.n0<`O017
.n0 the constant pi
` convert it into a string
O0 random number in the range [0.0, 1.0)
` convert to string
< 17 only use the first 17 chars (zero, point and 15 digits)
u for each char H in the pi-string:
?}HGH\x if H in G (the random number string) then H else "x"
p print this char without newline
& and
.-GH remove the digit H once from G
<space> suppress the output (u returns the unused digits in G)
JavaScript (ES6), (削除) 89 (削除ここまで) 87 bytes
_=>(r=[...Math.random()+""],Math.PI+"").replace(/./g,d=>(r[i=r.indexOf(d)]=_,~i?d:"x"))
Explanation
Edit: Random string is now not truncated as clarified by the poster.
Loops through each digit of pi and removes the digit from the random number if it was found, else replaces the digit in pi with x
.
_=>(
r=[...Math.random()+""], // r = array of 15 digit random number chars
Math.PI+"").replace(/./g,d=>( // for each digit d of pi, includes "." which is always
// in the random number
r[i=r.indexOf(d)]=_, // i = position of d within r, remove digit from r
// "_" is the unused function argument (equals undefined)
~i?d:"x" // if found, leave the digit, else replace with x
))
Test
Test outputs the random number also.
var solution = _=>(r=[...n=Math.random()+""],Math.PI+"").replace(/./g,d=>(r[i=r.indexOf(d)]=_,~i?d:"x"))
<button onclick="result.textContent='Result: '+solution()+'\nNumber: '+n">Go</button>
<pre id="result"></pre>
-
\$\begingroup\$ Couldn't random() produce 15 zeros in which would correspond to 0.000... or 1.000... ? i.e. not between 0 and 1. \$\endgroup\$Chris Degnen– Chris Degnen2015年12月21日 12:00:07 +00:00Commented Dec 21, 2015 at 12:00
-
\$\begingroup\$ @ChrisDegnen
Math.random()
produces a number of the range[0,1)
so it could0
but never1
. The OP didn't specifically state whether the range was inclusive or exclusive so I assumed that whatever was reasonable is fine. This is also the range that the other answers use. However you have made me aware that if it is exactly0
it will fail because the.
in pi will not be matched and becomex
. This has a 1 in 2^53 chance of happening but I decided to fixed it anyway. \$\endgroup\$user81655– user816552015年12月21日 12:20:42 +00:00Commented Dec 21, 2015 at 12:20 -
\$\begingroup\$ :-) sorry 'bout that. \$\endgroup\$Chris Degnen– Chris Degnen2015年12月21日 12:49:53 +00:00Commented Dec 21, 2015 at 12:49
-
\$\begingroup\$ The likelihood of hitting exactly 0 or 1 for a random double is negligible, so for the purpose of this challenge a range
[0,1]
is fine (so is(0,1)
). \$\endgroup\$Stewie Griffin– Stewie Griffin2015年12月21日 16:39:03 +00:00Commented Dec 21, 2015 at 16:39 -
\$\begingroup\$ Nice. I propose a shorter variant. \$\endgroup\$MST– MST2015年12月22日 05:49:39 +00:00Commented Dec 22, 2015 at 5:49
CJam, (削除) 48 (削除ここまで) (削除) 46 (削除ここまで) (削除) 42 (削除ここまで) (削除) 38 (削除ここまで) 36 bytes
P`'xf+1dmr`{1$f#:!1a/0=:)W+H<.%}/1f=
And here is the version which prints both π and the random number:
P_p`'xf+1dmr`_oNo{1$f#:!1a/0=:)W+H<.%}/1f=
I do not truncate the random number to 15 decimal places, as clarified by the OP in a comment.
Explanation
The idea is to turn each character in the string representation of π into a pair of that character and x
. For each character in the random number, we swap the first pair which starts with that character. At the end we output the second character of each pair.
P` e# Get string representation of π.
'xf+ e# Append "x" to each character.
1dmr` e# Get string representation of random number in [0,1).
{ e# For each character in that string...
1$ e# Copy the list of pairs.
f# e# For each pair, find the index of the current character. If the character is
e# not in the pair, we get -1 (truthy). If it is the first character of the pair,
e# we get 0 (falsy). If it is the second character, we get 1 (truthy).
:! e# Logical NOT for each of the results. We get a 1 for every pair we could
e# potentially swap.
1a/ e# Split around those 1s.
0= e# Keep only the first chunk.
:) e# Turn all the 0s into that chunk into 1s.
W+ e# Append a -1.
H< e# Truncate to 17 elements (the number of pairs).
.% e# Apply % pairwise. This reverses the element at the position of the -1.
}/
1f= e# Select the second character from each pair.
Lua, (削除) 231 (削除ここまで) 230 bytes
m,s=math,""p,r=m.pi..s,s..m.random()p=p:sub(1,#p-1)p:gsub(".",function(c)s=s..(47>c:byte()and c or"x")end)r:gsub("[^%.]",function(c)l=p:find(c)if l then p,s=p:sub(1,l-1).."x"..p:sub(l+1),s:sub(1,l-1)..c..s:sub(l+1)end end)print(s)
Explanations
function f()
m,s=math,""
p,r=m.pi..s,s..m.random()
p=p:sub(1,#p-1) -- remove the last digit of math.pi
p:gsub(".",function(c)
s=s..(47>c:byte()and c or"x") -- Construct a string full of "x" with a single dot
end)
r:gsub("[^%.]",function(c) -- Iterate over each character but the dot in the random number
l=p:find(c) -- if c isn't in pi, l=nil
if l -- which is one of the two falsy value in lua
then
p,s=p:sub(1,l-1).."x"..p:sub(l+1),-- If c is in pi, we replace it in p by an x
s:sub(1,l-1)..c..s:sub(l+1) -- and in s by its value
end
end)
return s
end
Sadly, lua doesn't help me at all here. math.pi round the last digit of pi it return :
print(math.pi)
>> 3.1415926535898
I have to truncate this number :
stringPI=""..math.pi
print(stringPI:sub(1,#stringPI-1))
>> 3.141592653589
The second big default to do this challenge was lua lack of string.replace(). As I'm doing this action twice using s:sub(1,l-1)..c..s:sub(l+1)
, I wanted to do an anonymous function, thinking it would be shorter. It isn't, so I kept it written twice.
The reason I have to be careful about the dot, is how lua return its position. In regexes, a dot mean "any character", so when i'm evaluating the character .
in my loop it matches the first character :
c="." -- The value of the dot in the loop
found = stringPI:find(c)
print(stringPI)
print("location of \".\": "..found)
print("char at "..found..": "..stringPI:sub(found,found))
>> 3.141592653589
>> location of ".": 1 --Keep in mind that lua arrays are 1-based :)
>> char at 1: 3
You can test lua online. As I am not seeding the PRNG, here's a code allowing you to run several test while still watching values.
function f()m,s=math,""p,r=m.pi..s,s..m.random()print("Random number: "..r)p=p:sub(1,#p-1)p:gsub(".",function(c)s=s..(c:byte()<47 and c or"x")end)r:gsub("[^%.]",function(c)l=p:find(c)if l then p,s=p:sub(1,l-1).."x"..p:sub(l+1),s:sub(1,l-1)..c..s:sub(l+1)end end)return s end
for i=1,10
do
print(f())
end
Python 2.7, (削除) 117 (削除ここまで) 110 bytes
import math,random
n=list(`random.random()`)
print''.join(n.pop(n.index(d))if d in n else'x'for d in`math.pi`)
Tested on the latest QPython Android app, but should work anywhere.
Edit 1: changed str(pi)
to backticks.
For testing:
import math,random
n=list(`random.random()`)
print `math.pi`
print ''.join(n)
print''.join(n.pop(n.index(d))if d in n else'x'for d in`math.pi`)
-
\$\begingroup\$ Nice answer! The "apostrophes SO uses to mark code" are backticks or grove symbols, by the way :-) \$\endgroup\$cat– cat2015年12月22日 02:30:08 +00:00Commented Dec 22, 2015 at 2:30
Python, 147 bytes
import math as m,random as r
L=lambda t:[_ for _ in str(t)]
p=L(m.pi)
R=L(r.random())
A=""
print R #subtracted from byte count
for n in p:
try:R.remove(n);A+=n
except:A+='x'
print A
Fairly self-explanatory: lambda function converts float to list; we then loop through the pi-list attempting to remove each digit from the random-list. If we can, good, append it to the answer; if not, append an 'x' instead.
-
\$\begingroup\$
str(t)
only gives you 11 digits of precision fromt
,repr(t)
gives you all oft
's 15 digits. \$\endgroup\$Noodle9– Noodle92015年12月21日 16:44:59 +00:00Commented Dec 21, 2015 at 16:44
Perl, 70 bytes
$_=4*atan2(1,1);s/\d/x$&/g;for$i(rand=~/\d/g){s/x$i/$i/}s/x./x/g;print
With comments:
$_=4*atan2(1,1); # Perl doesn't have a Pi constant
s/\d/x$&/g; # prepend a x to all digits in Pi
for $i (rand=~/\d/g) # iterate the digits in the random number
{ s/x$i/$i/ } # replace first occurrence of x-nr pair
s/x./x/g; # strip all remaining numbers
print # print!
This version will print pi, the random number, and the result:
$_=$p=4*atan2(1,1);
s/\d/x$&/g;
$r=rand;
for $i ($r=~/\d/g)
{ s/x$i/$i/ }
s/x./x/g;
print "$p\n$r\n$_\n"
Example output:
3.14159265358979
0.877757977767946
x.x4x59x6xxx897x
I hope this is okay:
- pi contains 15 digits total, including the 3, so it doesn't exceed accuracy.
- the last digit (
9
) is accurate.
0 < random < 1
or0 <= random <= 1
? \$\endgroup\$