A propos de la série
Je vais lancer une petite série de défis de code-golf autour du thème du hasard. Ce sera essentiellement un parcours de golf de 9 trous , mais divisé en plusieurs questions. Vous pouvez participer à n'importe quel défi individuellement, comme s'il s'agissait d'une question normale.
Cependant, je maintiendrai un classement dans tous les défis. La série se déroulera sur 9 défis (pour le moment), un posté tous les deux ou trois jours. Chaque utilisateur qui participe aux 9 défis est éligible pour gagner la série complète. Leur score global est la somme des soumissions les plus courtes sur chaque défi (donc si vous répondez deux fois à un défi, seule la meilleure réponse compte pour le score). Si quelqu'un occupe la première place de ce classement général pendant 28 jours, je lui attribuerai une prime de 500 reps .
Bien que de nombreuses idées soient en préparation pour la série, les défis à venir ne sont pas encore figés. Si vous avez des suggestions, veuillez me le faire savoir sur le message du bac à sable correspondant .
Trou 1: Mélangez un tableau
La première tâche est assez simple: mélangez-le aléatoirement avec un tableau d'entiers non vide. Il y a quelques règles cependant:
- Toutes les permutations possibles doivent être retournées avec la même probabilité (le brassage devrait donc avoir une distribution uniforme). Vous pouvez vérifier si votre algorithme est uniforme / non biaisé en l'implémentant en JavaScript dans Will it Shuffle , ce qui produira une matrice des biais - le résultat devrait être aussi uniforme que celui intégré dans Fisher-Yates ou être trié (ordre aléatoire) .
- Vous ne devez utiliser aucune méthode intégrée ou tierce partie pour mélanger le tableau ou générer une permutation aléatoire (ou énumérer toutes les permutations). En particulier, la seule fonction aléatoire intégrée que vous pouvez utiliser consiste à obtenir un seul nombre aléatoire à la fois . Vous pouvez supposer que toute méthode de nombre aléatoire intégrée s'exécute en O (1) et est parfaitement uniforme sur l'intervalle demandé (au sens mathématique - vous pouvez ignorer les détails de la représentation en virgule flottante ici). Si votre langue vous permet d’obtenir simultanément une liste de m nombres aléatoires, vous pouvez utiliser cette fonction, à condition que les m nombres soient indépendants les uns des autres et que vous les comptiez comme O (m).
- Votre implémentation ne doit pas dépasser une complexité temporelle de O (N) , où N est la taille de la matrice à mélanger. Par exemple, vous ne pouvez pas "trier par nombres aléatoires".
- Vous pouvez soit mélanger le tableau à la place, soit créer un nouveau tableau (auquel cas l'ancien tableau peut être modifié à votre guise).
Vous pouvez écrire un programme complet ou une fonction et effectuer une entrée via STDIN, un argument de ligne de commande, un argument de fonction ou une invite et produire une sortie via une valeur de retour ou en imprimant sur STDOUT (ou son alternative la plus proche). Si vous écrivez une fonction qui mélange le tableau en place, vous n'avez évidemment pas besoin de la renvoyer (à condition que votre langue vous permette d'accéder au tableau modifié après le retour de la fonction).
Les entrées et les sorties peuvent se présenter sous n'importe quelle liste ou format de chaîne, mais doivent prendre en charge des entiers quelconques compris dans la plage -2 31 ≤ x <2 31 . En principe, votre code devrait fonctionner pour les tableaux d'une longueur maximale de 2 à 31 , bien que cela ne doive pas nécessairement être enregistré dans votre mémoire ou terminé dans un délai raisonnable. (Je ne veux tout simplement pas voir des limites de taille arbitraires pour les boucles en code fixe ou quelque chose du genre.)
C'est le code de golf, donc la soumission la plus courte (en octets) gagne.
Classement
L'extrait suivant générera un classement pour tous les défis de la série.
Pour vous assurer que vos réponses apparaissent, commencez chaque réponse par un titre, en utilisant le modèle Markdown suivant:
# Language Name, N bytes
où N
est la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores en les effaçant. Par exemple:
# Ruby, <s>104</s> <s>101</s> 96 bytes
(La langue n'est pas affichée pour le moment, mais l'extrait de code nécessite une analyse syntaxique. Il se peut que j'ajoute un classement par langue ultérieurement.)
/* Configuration */
var QUESTION_IDs = [45302, 45447, 46991, 49394, 51222, 66319, 89621, 120472]; // Obtain this from the url
// It will be like http://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!.FjwQBrX2KXuFkv6p2lChi_RjzM19";
/* App */
var answers = [], page = 1, currentQ = -1;
function answersUrl(index) {
return "https://api.stackexchange.com/2.2/questions/" + QUESTION_IDs.join(";") + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}
function getAnswers() {
$.ajax({
url: answersUrl(page++),
method: "get",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
answers.push.apply(answers, data.items);
if (data.has_more) getAnswers();
else process();
}
});
}
getAnswers();
var SIZE_REG = /\d+(?=[^\d&]*(?:<(?:s>((?!>).)*<\/s>|((?!>).)+>)[^\d&]*)*$)/;
var NUMBER_REG = /\d+/;
var LANGUAGE_REG = /^#*\s*([^\n,]+)(?=,)/;//
function shouldHaveHeading(a) {
var pass = false;
var lines = a.body_markdown.split("\n");
try {
pass |= /^#/.test(a.body_markdown);
pass |= ["-", "="]
.indexOf(lines[1][0]) > -1;
pass &= LANGUAGE_REG.test(a.body_markdown);
} catch (ex) {}
return pass;
}
function shouldHaveScore(a) {
var pass = false;
try {
pass |= SIZE_REG.test(a.body_markdown.split("\n")[0]);
} catch (ex) {}
if (!pass) console.log(a);
return pass;
}
function getAuthorName(a) {
return a.owner.display_name;
}
function getAuthorId(a) {
return a.owner.user_id;
}
function process() {
answers = answers.filter(shouldHaveScore)
.filter(shouldHaveHeading);
answers.sort(function (a, b) {
var aB = +(a.body_markdown.split("\n")[0].match(SIZE_REG) || [Infinity])[0],
bB = +(b.body_markdown.split("\n")[0].match(SIZE_REG) || [Infinity])[0];
return aB - bB
});
var users = {};
answers.forEach(function (a) {
var headline = a.body_markdown.split("\n")[0];
var question = QUESTION_IDs.indexOf(a.question_id);
var size = parseInt((headline.match(SIZE_REG)||[0])[0]);
var language = headline.match(LANGUAGE_REG)[1];
var user = getAuthorName(a);
var userId = getAuthorId(a);
if (!users[userId]) users[userId] = {name: user, nAnswer: 0, answers: []};
if (!users[userId].answers[question]) {
users[userId].answers[question] = {size: Infinity};
users[userId].nAnswer++;
}
if (users[userId].answers[question].size > size) {
users[userId].answers[question] = {size: size, link: a.share_link}
}
});
var sortedUsers = [];
for (var userId in users)
if (users.hasOwnProperty(userId)) {
var user = users[userId];
user.score = 0;
user.completedAll = true;
for (var i = 0; i < QUESTION_IDs.length; ++i) {
if (user.answers[i])
user.score += user.answers[i].size;
else
user.completedAll = false;
}
sortedUsers.push(user);
}
sortedUsers.sort(function (a, b) {
if (a.nAnswer > b.nAnswer) return -1;
if (b.nAnswer > a.nAnswer) return 1;
return a.score - b.score;
});
var place = 1;
for (var i = 0; i < sortedUsers.length; ++i) {
var user = sortedUsers[i];
var row = '<tr><td>'+ place++ +'.</td><td>'+user.name+'</td>';
for (var j = 0; j < QUESTION_IDs.length; ++j) {
var answer = user.answers[j];
if (answer)
row += '<td><a href="'+answer.link+'">'+answer.size+'</a></td>';
else
row += '<td class="missing"></td>';
}
row += '<td></td>';
if (user.completedAll)
row += '<td class="total">'+user.score+'</td>';
else
row += '<td class="total missing">'+user.score+'</td>';
row += '</tr>';
$("#users").append(row);
}
}
body { text-align: left !important}
#leaderboard {
width: 500px;
}
#answer-list {
padding: 10px;
width: 290px;
float: left;
}
#language-list {
padding: 10px;
width: 290px;
float: left;
}
table thead {
font-weight: bold;
}
table td {
padding: 5px;
}
td.total {
font-weight: bold;
text-align: right;
}
td.missing {
background: #bbbbbb;
}
<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="leaderboard">
<h2>Leaderboard</h2>
<p>
Missing scores are shown as grey cells. A grey total indicates that the user has not participated in all challenges and is not eligible for the overall victory yet.
</p>
<table class="_user-list">
<thead>
<tr><td></td><td>User</td>
<td><a href="https://codegolf.stackexchange.com/q/45302/8478">#1</a></td>
<td><a href="https://codegolf.stackexchange.com/q/45447/8478">#2</a></td>
<td><a href="https://codegolf.stackexchange.com/q/46991/8478">#3</a></td>
<td><a href="https://codegolf.stackexchange.com/q/49394/8478">#4</a></td>
<td><a href="https://codegolf.stackexchange.com/q/51222/8478">#5</a></td>
<td><a href="https://codegolf.stackexchange.com/q/66319/8478">#6</a></td>
<td><a href="https://codegolf.stackexchange.com/q/89621/8478">#7</a></td>
<td><a href="https://codegolf.stackexchange.com/q/120472/8478">#8</a></td>
<td></td><td>Total</td>
</tr>
</thead>
<tbody id="users">
</tbody>
</table>
</div>
<table style="display: none">
<tbody id="answer-template">
<tr><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>
sortby(random)
(la raison de la restriction temporelle), soit simplement.shuffle()
(la raison de la restriction intégrée), ce qui est beaucoup moins intelligent, à mon avis, que de devoir mettre en œuvre Fisher-Yates ou un autre. approche.shuffle(array)
au lieu denewArray=shuffle(array)
?Réponses:
Dyalog APL,
2524 bytesFirst for the 25-character solution:
i{⊃a[⍺⍵]←a[⍵⍺]}¨?i←⌽⍳⍴a←⎕
After some equivalence transformations on the above:
we can get rid of the assignment
i←
and save a character:{⊃a[⍺⍵]←a[⍵⍺]}¨∘?⍨⌽⍳⍴a←⎕
la source
80386 machine code,
4424 bytesHexdump of the code:
Thanks to FUZxxl, who suggested using the
rdrand
instruction.Here is the source code (can be compiled by Visual Studio):
Yet another Fisher-Yates implementation. Most of the golfing was achieved by passing parameters in registers.
la source
rdrand
for shits and giggles.Java, 88
101A basic Fisher-Yates shuffle does the trick. I get the feeling it'll be used pretty commonly here, since it's quick and easy to implement. There's some loop/assignment cramming here, but there's honestly not too much to golf; it's just short by nature.
With some line breaks:
This shuffles in place, modifying the original array
s[]
. Test program:la source
Math.random()
has a size which is a power of two, so this doesn't meet spec.Python 2, 86 bytes
This is a function which shuffles the array in place without returning it, using a straightforward implementation of the Fisher-Yates shuffle. Getting random numbers from Python is expensive...
Thanks to @xnor and @colevk for tips.
la source
while i:i-=1;...
?while
tends to be shorter thanfor
for this sort of thing...i=len(L)
and putting the decrement at the beginning of the while loop.J,
4544 charactersThis was a tricky one.
Here is an explanation:
# y
: The tally ofy
, that is, the number of elements iny
.?@# y
: A random number uniformly distributed over the range from1
to(#y)-1
.x { y
: The item fromy
at indexx
.(<<<x) { y
: All items except the item at indexx
iny
.x , y
:y
appended tox
.x ({ , <^:3@[ { ]) y
: The item at indexx
iny
, then all the other items.(?@# ({ , <^:3@[ { ]) ]) y
A random it fromy
, then all the other items.x {. y
: The firstx
items taken fromy
.x }. y
: The firstx
items dropped fromy
.x ({. , }.) y
: The firstx
items taken fromy
, then the firstx
items dropped fromy
x ({. , (?@# ({ , <^:3@[ { ]) ])@}.) y
: The firstx
items taken fromy
, then the firstx
items fromy
processed as in number 7.x ({. , ?@#@}. ({ , <^:3@[ { ]) }.) y
: The same thing with the drop pulled in to save one character.u/ y
:u
inserted between the items ofy
.< y
:y
boxed.<"0 y
: Each item ofy
boxed.i. y
: integers from0
toy - 1
.i.@# y
: integers from0
to(#y) - 1
.(<"0@i.@# , <) y
: Integers from0
to(#y) - 1
each boxed and theny
in a single box. This is needed because arrays in J are uniform. A box hides the shape of its content.x u&v y
: like(v x) u (v y)
.> y
:y
opened, that is, without its box.x ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&> y
the phrase from number 12 applied to its unboxed arguments.({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/ y
the phrase from number 21 inserted between items ofy
.({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/@(<"0@i.@# , <) y
the phrase from number 22 applied to the the result of the phrase from number 18, or, a uniform permutation of the items ofy
.la source
<@<@<@[
is also a mystery... Waiting for explanation. :)from
({
). And I really like the&>/
trick to manipulate a list. I'm sure I could have used it a couple times before.Pyth, 25 bytes
Test it here.
Yet another Fisher-Yates implementation. Is essentially the same as @Sp3000 python solution, just in pyth.
Thanks to @Jakube for the swapping trick
la source
Perl,
685644Like many other solutions, this uses the Fisher-Yates algorithm.
Using nutki's comment, 12 characters are saved by using
$_
instead of$i
and performing the operations in the array indices.44:
56:
This is my first codegolf.
la source
@_[...]
as rvalue like that. Can be golfed further intosub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}
.C,
636160 bytesJust a straight implementation of Fischer-Yates that sorts the given array in place. Compiles and links perfectly fine with the visual studio compiler (vs2013, haven't tested the other versions) and the Intel Compiler. Nice looking function signature is
s(int array[], int length)
. I'm legitimately impressed I beat Python and Ruby.This does assume
srand()
is called and rand() is implemented properly, but I believe this rule allows for that:Nicely formatted version:
la source
s(a,m)*a{
, but I'm not sure and don't want to test either. You might want to do axor
-swap, like ina[i]^=a[m]^=a[i]^=a[m]
. This also avoids the need to declaret
.i==m
.s(a,m)int*a
for visual studio and the intel compiler. Don't have gcc or clang installed to test, but I assume they will also complain.t=a[i]
, you can then move thei=rand()%m--
statement inside as the array index.Octave,
8877 bytesYet another Fisher-Yates implementation... Should be fairly straightforward if I add the usual line returns and spacing:
The "end" keywords really kill the golf score here, unfortunately.Hey, I can use "end" instead of "endfor" and "endfunction"!la source
numel
instead oflenght
. As a bonus your program would also work with 2-D arrays aka matrices ;)Java 8, 77
It's a lambda taking
int[]
and returning void. My first attempt seemed not very interesting, so I decided to have it exit by throwing an exception.Test program:
la source
Math.random()
?Golflua, 37
How to run Golflua?
The input is provided as a table in the variable X. The table is shuffled in place.
Example usage:
la source
R, 79 bytes
This is a straightforward implementation of the Fisher-Yates shuffle. The R function
sample
draws a simple random sample of a given size from a given vector with equal probability. Here we're drawing a random sample of size 1 at each iteration from the integersi
, ...,n
. As stated in the question, this can be assumed to be O(1), so in all this implementation should be O(N).la source
Matlab, 67
Also implementing Fisher-Yates.
I thought it was too bad I could not use Matlab's
randperm
function. But after some fiddling around, I thought I may look at the source ofrandperm
to see how it is done, and I was astonished to see that there was just one line:[~,p] = sort(rand(1,n))
=)la source
Perl, 44
Another perl in 44 characters. Example use:
la source
Mathematica,
82 90 8393 bytesNote: This variation the Fisher-Yates shuffle is actually Martin Büttner's solution, with some code paring by alephalpha.
s
is the input array. Nothing fancy-smancy, but sometimes the simple things are the most elusive.la source
Do
here. It's shorter thanWhile
.Ruby, 57 bytes
Input (as lambda function):
Output:
la source
TI-BASIC, 46 bytes
Source for byte count
la source
End
.K, 31 chars
Not quite as short as the one I put up before (which got disqualified)...oh well.
It's a basic Fisher-Yates shuffle. This was built with lots of help from the Kona mailing list.
la source
JavaScript (ES6), 66
This function shuffles the array in place. It also returns a byproduct array that is NOT the shuffled output and must not be considered.
la source
MATL, 16 bytes
Try it online!
Fisher-Yates in MATL. Almost a third of this program is devoted to the letter
H
, which corresponds to the clipboard function in MATL.Basically,
H
stores the unused items from the input, while the stack keeps track of the shuffled list.la source
Japt, 12
Try it!
-10 (about half ;) thanks to @Shaggy!
I have been wanting to try out a golfing language, and the Japt interpreter had good documentation and a way to try things out in the browser.
Below is the strategy I took:
la source
Javascript ES6, 69
It's Fisher–Yates.
PS: Can be tested in Firefox
la source
Pyth, 27 bytes
Test it here
This is an implementation of the incremental Fisher-Yates shuffle, mentioned second here.
la source
Haskell, 170
Another Fisher-Yates solution inspired by the algorithm at https://wiki.haskell.org/Random_shuffle.
s
is a function which has signature:IOArray Int a -> IO [a]
la source
CJam - 30
Try it at http://cjam.aditsu.net/
Example input:
[10 20 30 40 50]
Example output:
3020401050
(add ap
at the end of the code for pretty printing)If the code is allowed to take the input from the stack (like a function), then the first 2 characters can be removed, reducing the size to 28.Explanation:
The code is longer than I hoped, due to the lack of a "swap" operator for arrays
(to be implemented later :p)
la source
_
is O(N) (inside an O(N) loop). Unfortunately, I don't see a way to work around that in CJam.t
that kills it, as it can't mutate the list and now must create a copy.t
, I'd like to improve it in future versions..JavaScript (ES 6), 61
You can test it here by just adding a line that says
shuffle = S
(Firefox only).la source
STATA, 161
Expects input as space separated numbers. I can remove the headers and observation numbers from the output if you would like, but otherwise this is shorter.
la source
_n
in this?Java, 93 bytes
Example usage: http://ideone.com/RqSMnZ
la source
SQF, 91 bytes
la source
%x
with%i
.Perl, 41 bytes
Try it online!
la source