Про серію
Я буду проводити невелику серію проблем із кодовим гольфом, що обертаються навколо теми випадковості. Це в основному поле для гольфу з 9 отворами , але буде розкрито на кілька питань. Ви можете брати участь у будь-якому виклику індивідуально, ніби це було звичайним питанням.
Однак я буду підтримувати таблицю лідерів у всіх викликах. Серія матиме 9 викликів (поки що), один розміщений кожні кілька днів. Кожен користувач, який бере участь у всіх 9 викликах, має право виграти всю серію. Їх загальний бал - це сума їх найкоротших подань на кожен виклик (тому якщо ви відповісте на виклик двічі, до балу зараховується лише краща відповідь). Якщо хтось займає перше місце в цьому загальному лідері протягом 28 днів, я присуджую їм суму в 500 респ .
Хоча у мене є маса ідей, що вибудовуються для цієї серії, майбутні виклики ще не поставлені перед каменем. Якщо у вас є якісь пропозиції, будь ласка, повідомте мене про це у відповідній поштовій скриньці .
Отвір 1: Перемішати масив
Перше завдання досить просте: даючи не порожній масив цілих чисел, переміщуйте його випадковим чином. Однак є кілька правил:
- Кожна можлива перестановка повинна повертатися з однаковою ймовірністю (тому перетасування має мати рівномірний розподіл). Ви можете перевірити, чи ваш алгоритм є рівномірним / неупередженим, застосувавши його в JavaScript на " Will it Shuffle" , який створить матрицю зміщення - результат повинен виглядати однаково, як їх вбудовані Fisher-Yates або сортувати (випадковий порядок) .
- Ви не повинні використовувати будь-який вбудований або сторонній метод для переміщення масиву або генерації випадкової перестановки (або перерахування всіх перестановок). Зокрема, єдиною вбудованою випадковою функцією, яку ви можете використовувати, є отримання одиничного випадкового числа одночасно . Ви можете припустити, що будь-який вбудований метод випадкових чисел працює в O (1) і ідеально рівномірний протягом запитуваного інтервалу (в математичному сенсі - ви можете ігнорувати тут деталі подання з плаваючою комою). Якщо ваша мова дозволяє одразу отримати список m випадкових чисел, ви можете скористатися цим засобом, якщо m числа не залежать один від одного, і ви порахуєте його як O (m).
- Ваша реалізація не повинна перевищувати часову складність O (N) , де N - розмір масиву, який потрібно перемістити. Наприклад, ви не можете "сортувати за випадковими числами".
- Ви можете або перетасувати масив на місці, або створити новий масив (у такому випадку старий масив може бути змінений, як вам завгодно).
Ви можете написати повну програму або функцію та взяти вхід через STDIN, аргумент командного рядка, аргумент функції або підказку та отримати висновок через повернене значення або надрукувавши STDOUT (або найближчу альтернативу). Якщо ви пишете функцію, яка переміщує масив на місці, вам, звичайно, не потрібно повертати її (за умови, що ваша мова дозволяє отримати доступ до модифікованого масиву після повернення функції).
Введення та вихід можуть бути у будь-якому зручному списку чи рядковому форматі, але повинні підтримувати довільні цілі числа в діапазоні -2 31 ≤ x <2 31 . В принципі, ваш код повинен працювати для масивів довжиною до 2 31 , хоча це не обов'язково має вміщуватися у вашій пам'яті або заповнюватися протягом розумного часу. (Я просто не хочу бачити довільні обмеження розміру для циклів жорсткого коду чи чогось іншого.)
Це код гольфу, тому виграє найкоротше подання (у байтах).
Таблиця лідерів
Наступний фрагмент створить таблицю лідерів у всіх викликах серії.
Щоб відповіді відображалися, почніть кожну відповідь із заголовка, використовуючи такий шаблон Markdown:
# Language Name, N bytes
де N
розмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:
# Ruby, <s>104</s> <s>101</s> 96 bytes
(Мова наразі не відображається, але фрагмент вимагає і аналізує його, і я можу в майбутньому додати таблицю лідерів за мовою.)
/* 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>