Sobre a série
Estarei executando uma pequena série de desafios de código-golfe que giram em torno do tema da aleatoriedade. Basicamente, este será um campo de golfe de 9 buracos , mas está espalhado por várias perguntas. Você pode participar de qualquer desafio individualmente, como se fosse uma pergunta normal.
No entanto, manterei uma tabela de líderes em todos os desafios. A série terá 9 desafios (por enquanto), um publicado a cada poucos dias. Todo usuário que participa dos nove desafios é elegível para ganhar a série inteira. A pontuação geral deles é a soma dos envios mais curtos em cada desafio (portanto, se você responder a um desafio duas vezes, apenas a melhor resposta será contada na pontuação). Se alguém ocupar o primeiro lugar nesta classificação geral por 28 dias , concederei a eles uma recompensa de 500 representantes .
Embora eu tenha várias idéias alinhadas para a série, os desafios futuros ainda não estão definidos. Se você tiver alguma sugestão, informe-me na postagem da sandbox relevante .
Buraco 1: embaralhar uma matriz
A primeira tarefa é bem simples: dada uma matriz não vazia de números inteiros, embaralhe-a aleatoriamente. Existem algumas regras, porém:
- Toda permutação possível deve ser retornada com a mesma probabilidade (para que o shuffle tenha uma distribuição uniforme). Você pode verificar se o seu algoritmo é uniforme / imparcial implementando-o em JavaScript no Will it Shuffle , que produzirá uma matriz de vieses - o resultado deve parecer tão uniforme quanto seus Fisher-Yates internos ou classificação (ordem aleatória) .
- Você não deve usar nenhum método interno ou de terceiros para embaralhar a matriz ou gerar uma permutação aleatória (ou enumerar todas as permutações). Em particular, a única função aleatória interna que você pode usar é obter um único número aleatório de cada vez . Você pode assumir que qualquer método de número aleatório interno é executado em O (1) e é perfeitamente uniforme durante o intervalo solicitado (em um sentido matemático - você pode ignorar detalhes da representação em ponto flutuante aqui). Se o seu idioma permitir que você obtenha uma lista de m números aleatórios de uma só vez, você poderá usar este recurso, desde que os números m sejam independentes um do outro e contados como O (m).
- Sua implementação não deve exceder uma complexidade de tempo de O (N) , em que N é o tamanho da matriz a ser embaralhada. Por exemplo, você não pode "classificar por números aleatórios".
- Você pode embaralhar a matriz no lugar ou criar uma nova matriz (nesse caso, a matriz antiga pode ser modificada da maneira que desejar).
Você pode escrever um programa completo ou uma função e receber entradas via STDIN, argumento de linha de comando, argumento de função ou prompt e produzir saída via valor de retorno ou imprimindo em STDOUT (ou alternativa mais próxima). Se você escrever uma função que embaralhe a matriz no lugar, não precisará retorná-la, é claro (desde que o seu idioma permita acessar a matriz modificada após o retorno da função).
A entrada e a saída podem estar em qualquer formato conveniente de lista ou sequência, mas devem suportar números inteiros arbitrários no intervalo -2 31 ≤ x <2 31 . Em princípio, seu código deve funcionar com matrizes de comprimento 2 a 31 , embora isso não precise necessariamente caber em sua memória ou ser concluído dentro de um período de tempo razoável. (Eu só não quero ver limites arbitrários de tamanho para loops de código rígido ou algo assim.)
Isso é código de golfe, então a submissão mais curta (em bytes) vence.
Entre os melhores
O trecho a seguir gerará uma tabela de classificação em todos os desafios da série.
Para garantir que suas respostas sejam exibidas, inicie todas as respostas com um título, usando o seguinte modelo de remarcação:
# Language Name, N bytes
onde N
está o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:
# Ruby, <s>104</s> <s>101</s> 96 bytes
(O idioma não é mostrado no momento, mas o snippet exige e o analisa, e eu posso adicionar um cabeçalho por idioma no futuro.)
/* 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)
(a razão da restrição de tempo) ou simplesmente.shuffle()
(a razão da restrição de embutidos), que eu acho muito menos inteligente do que ter que implementar Fisher-Yates ou alguma outra aproximação.shuffle(array)
vez denewArray=shuffle(array)
?Respostas:
Dyalog APL,
2524 bytesPrimeiro para a solução de 25 caracteres:
i{⊃a[⍺⍵]←a[⍵⍺]}¨?i←⌽⍳⍴a←⎕
Após algumas transformações de equivalência acima:
podemos nos livrar da tarefa
i←
e salvar um personagem:{⊃a[⍺⍵]←a[⍵⍺]}¨∘?⍨⌽⍳⍴a←⎕
fonte
Código de máquina 80386,
4424 bytesHexdump do código:
Agradecimentos a FUZxxl, que sugeriu o uso da
rdrand
instrução.Aqui está o código fonte (pode ser compilado pelo Visual Studio):
Mais uma implementação de Fisher-Yates. A maior parte do golfe foi alcançada através da passagem de parâmetros nos registros.
fonte
rdrand
para merdas e risadinhas.Java, 88
101Um embaralhamento básico de Fisher-Yates faz o truque. Sinto que ele será usado com bastante frequência aqui, pois é rápido e fácil de implementar. Há alguns loops / tarefas aqui, mas honestamente não há muito para jogar golfe; é apenas curto por natureza.
Com algumas quebras de linha:
Isso muda de lugar, modificando a matriz original
s[]
. Programa de teste:fonte
Math.random()
tem um tamanho que é uma potência de dois, portanto, isso não atende às especificações.Python 2, 86 bytes
Essa é uma função que embaralha a matriz no lugar sem retorná-la, usando uma implementação direta do embaralhamento Fisher-Yates . Obter números aleatórios do Python é caro ...
Obrigado a @xnor e @colevk por dicas.
fonte
while i:i-=1;...
?while
tende a ser mais curto do quefor
para este tipo de coisa ...i=len(L)
e colocando o decremento no início do loop while.J,
4544 caracteresEste foi um assunto complicado.
Aqui está uma explicação:
# y
: A contagem dey
, isto é, o número de elementos emy
.?@# y
: Um número aleatório distribuído uniformemente no intervalo de1
até(#y)-1
.x { y
: O item dey
no índicex
.(<<<x) { y
: Todos os itens, exceto o item no índicex
emy
.x , y
:y
anexado ax
.x ({ , <^:3@[ { ]) y
O item no índicex
emy
, em seguida, todos os outros itens.(?@# ({ , <^:3@[ { ]) ]) y
Um aleatórioy
, e todos os outros itens.x {. y
: Os primeirosx
itens tomadas a partiry
.x }. y
: Os primeirosx
itens caiu dey
.x ({. , }.) y
: Os primeirosx
itens tomadas a partiry
, então os primeirosx
itens caiu dey
x ({. , (?@# ({ , <^:3@[ { ]) ])@}.) y
: Os primeirosx
itens tomadas a partiry
, então a primeirax
itens dey
processados tal como no número 7.x ({. , ?@#@}. ({ , <^:3@[ { ]) }.) y
: A mesma coisa com a gota puxada para salvar um personagem.u/ y
:u
inserido entre os itens dey
.< y
: emy
caixa .<"0 y
: Cada item day
caixa .i. y
: números inteiros de0
atéy - 1
.i.@# y
: números inteiros de0
até(#y) - 1
.(<"0@i.@# , <) y
: Números inteiros de0
para(#y) - 1
cada caixa e,y
em seguida, em uma única caixa. Isso é necessário porque matrizes em J são uniformes. Uma caixa oculta a forma do seu conteúdo.x u&v y
: como(v x) u (v y)
.> y
:y
aberto , ou seja, sem sua caixa.x ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&> y
a frase do número 12 se aplica a seus argumentos sem caixa.({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/ y
a frase do número 21 inserida entre os itens dey
.({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/@(<"0@i.@# , <) y
a frase do número 22 aplicada ao resultado da frase do número 18 ou uma permutação uniforme dos itens dey
.fonte
<@<@<@[
também é um mistério ... Esperando por explicações. :)from
({
). E eu realmente gosto do&>/
truque para manipular uma lista. Tenho certeza de que poderia usá-lo algumas vezes antes.Pitão, 25 bytes
Teste aqui.
Mais uma implementação de Fisher-Yates. É essencialmente o mesmo que a solução python @ Sp3000, apenas em pyth.
Obrigado a @Jakube pelo truque de troca
fonte
Perl,
685644Como muitas outras soluções, isso usa o Fisher-Yates algoritmo .
Usando o comentário de nutki , 12 caracteres são salvos usando em
$_
vez de$i
e executando as operações nos índices da matriz.44:
56:
Este é o meu primeiro codegolf.
fonte
@_[...]
como rvalue assim. Pode ser jogado ainda maissub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}
.C,
636160 bytesApenas uma implementação direta do Fischer-Yates que classifica a matriz fornecida no local. Compila e vincula perfeitamente com o compilador visual studio (vs2013, não testou as outras versões) e o compilador Intel. A assinatura da função de aparência agradável é
s(int array[], int length)
. Estou legitimamente impressionado por vencer o Python e o Ruby.Isso assume que
srand()
é chamado e rand () é implementado corretamente, mas acredito que esta regra permite isso:Versão bem formatada:
fonte
s(a,m)*a{
, mas não tenho certeza e não quero testar também. Você pode fazer umxor
swap, como ema[i]^=a[m]^=a[i]^=a[m]
. Isso também evita a necessidade de declarart
.i==m
.s(a,m)int*a
do visual studio e do compilador intel. Não tem o gcc ou o clang instalado para testar, mas presumo que eles também irão reclamar.t=a[i]
, você poderá mover ai=rand()%m--
instrução para dentro como o índice da matriz.Oitava,
8877 bytesAinda outra implementação de Fisher-Yates ... Deveria ser bastante direta se eu adicionar os retornos e espaçamentos usuais da linha:
As palavras-chave "final" realmente matam a pontuação de golfe aqui, infelizmente.Ei, eu posso usar "end" em vez de "endfor" e "endfunction"!fonte
numel
vez delenght
. Como um bônus seu programa também trabalhar com matrizes 2-D aka matrizes;)Java 8, 77
É uma lambda tomando
int[]
e retornando vazio. Minha primeira tentativa não pareceu muito interessante, então decidi sair lançando uma exceção.Programa de teste:
fonte
Math.random()
?Golflua, 37
Como executar o Golflua?
A entrada é fornecida como uma tabela na variável X. A tabela é embaralhada no lugar.
Exemplo de uso:
fonte
R, 79 bytes
Esta é uma implementação direta do shuffle de Fisher-Yates. A função R
sample
desenha uma amostra aleatória simples de um determinado tamanho de um determinado vetor com igual probabilidade. Aqui estamos desenhando uma amostra aleatória do tamanho 1 em cada iteração a partir dos números inteirosi
, ...,n
. Como afirmado na pergunta, isso pode ser assumido como O (1); portanto, em toda essa implementação deve ser O (N).fonte
Matlab, 67
Também implementando Fisher-Yates.
Achei muito ruim não poder usar a
randperm
função do Matlab . Mas, depois de algumas brincadeiras, pensei em ver a fonterandperm
para ver como isso é feito, e fiquei surpreso ao ver que havia apenas uma linha:[~,p] = sort(rand(1,n))
=)fonte
Perl, 44
Outro perl em 44 caracteres. Exemplo de uso:
fonte
Mathematica,
82 90 8393 bytesNota: Essa variação do embaralhamento de Fisher-Yates é na verdade a solução de Martin Büttner, com algum código aparecendo por alefalpha.
s
é a matriz de entrada. Nada de sofisticação, mas às vezes as coisas simples são as mais esquivas.fonte
Do
aqui. É mais curto queWhile
.Ruby, 57 bytes
Entrada (como função lambda):
Saída:
fonte
TI-BASIC, 46 bytes
Origem para contagem de bytes
fonte
End
.K, 31 caracteres
Não é tão curto quanto o que eu coloquei antes (que foi desclassificado) ... tudo bem.
É um embaralhamento básico de Fisher-Yates. Isso foi construído com muita ajuda da lista de discussão Kona .
fonte
JavaScript (ES6), 66
Essa função embaralha a matriz no lugar. Ele também retorna uma matriz de subprodutos que NÃO é a saída aleatória e não deve ser considerada.
fonte
MATL , 16 bytes
Experimente online!
Fisher-Yates em MATL. Quase um terço deste programa é dedicado à letra
H
, que corresponde à função da área de transferência no MATL.Basicamente,
H
armazena os itens não utilizados da entrada, enquanto a pilha controla a lista aleatória.fonte
Japt, 12
Tente!
-10 (cerca de metade;) graças a @Shaggy!
Eu estava querendo experimentar uma linguagem de golfe, e o intérprete Japt tinha boa documentação e uma maneira de experimentar as coisas no navegador.
Abaixo está a estratégia que tomei:
fonte
Javascript ES6, 69
É o Fisher-Yates.
PS: Pode ser testado no Firefox
fonte
Pitão, 27 bytes
Teste aqui
Esta é uma implementação do shuffle incremental de Fisher-Yates, mencionado em segundo lugar aqui .
fonte
Haskell, 170
Outra solução Fisher-Yates inspirada no algoritmo em https://wiki.haskell.org/Random_shuffle .
s
é uma função que possui assinatura:IOArray Int a -> IO [a]
fonte
CJam - 30
Experimente em http://cjam.aditsu.net/
Exemplo de entrada:
[10 20 30 40 50]
Exemplo de saída:
3020401050
(adicione ap
no final do código para obter uma impressão bonita)Se o código puder receber a entrada da pilha (como uma função), os 2 primeiros caracteres poderão ser removidos, reduzindo o tamanho para 28.Explicação:
O código é mais longo do que eu esperava, devido à falta de um operador "swap" para matrizes
(a ser implementado posteriormente: p)
fonte
_
é O (N) (dentro de um loop O (N)). Infelizmente, não vejo uma maneira de contornar isso no CJam.t
isso que mata, já que não pode alterar a lista e agora deve criar uma cópia.t
, eu gostaria de melhorá-lo em versões futuras ..JavaScript (ES 6), 61
Você pode testá-lo aqui , apenas adicionando uma linha que diz
shuffle = S
(apenas Firefox).fonte
STATA, 161
Espera entrada como números separados por espaço. Posso remover os cabeçalhos e os números de observação da saída, se você quiser, mas, caso contrário, isso é mais curto.
fonte
_n
nisso?Java, 93 bytes
Exemplo de uso: http://ideone.com/RqSMnZ
fonte
SQF, 91 bytes
fonte
%x
por%i
.Perl, 41 bytes
Experimente online!
fonte