N Двери, K Обезьяны


14

Есть N дверей и K обезьян. Изначально все двери закрыты.

Раунд 1: 1-ая обезьяна посещает каждую дверь и переключает дверь (если дверь закрыта, она открывается; если она открыта, она закрывается).

Раунд 2 : 1-я обезьяна посещает каждую дверь и переключает дверь. Затем Вторая Обезьяна посещает каждую 2-ю дверь и переключает дверь.

, , ,

, , ,

Раунд k: 1-я обезьяна посещает каждую дверь и переключает дверь. , , , , , , , , , K-я обезьяна посещает каждую K-ую дверь и переключает дверь.

Ввод: NK (разделенный одним пробелом)

Вывод: номера дверей, которые открыты, каждая разделена одним пробелом.

Пример :

Вход: 3 3

Выход: 1 2

Ограничения :

0 <N <101

0 <= K <= N

Примечание :

  • Предположим, что N дверей пронумерованы от 1 до N, а K обезьян пронумерованы от 1 до K

  • Победит тот, у кого самый короткий код. Кроме того, вывод на дисплей для N = 23, K = 21



У меня просто вопрос, если N = K, все простые числа открыты, верно?
Fabinout

@Fabinout no n=k=3будет выводить, 1 2так что вы не правы ... и 5 выходов 1 2 4есть шаблон, но его гораздо менее очевидно, чем это.
Математический чиллер

@Fabinout это следует за очень странным типом набора чисел Фибоначчи, его очень продвинутой абстрактной математикой.
Математический чиллер

@tringToGetProgrammingStraight вы правы, мои воспоминания подсказали мне, что ответом был список простых чисел, когда это был список квадратных чисел.
Fabinout

Ответы:


14

APL, 32 28 26

{(2|+/(⍳⍺)∘.{+/0=⍺|⍨⍳⍵}⍳⍵)/⍳⍺}/⎕

⎕:
      23 21
 1 2 4 8 9 16 18 23 

Explaination

  • {+/0=⍺|⍨⍳⍵}это функция, которая возвращает количество раз, когда дверь (левый аргумент) переключается на раунд (правый аргумент), что равно количеству факторов этого ≤ :

    • ⍳⍵ Создать числовой массив от 1 до

    • ⍺|⍨Рассчитать модуль каждого элемента этого массива

    • 0= Измените на 1, где было 0, и 0 для всех остальных

    • +/ Суммируйте полученный массив

  • Внешняя функция:

    • (⍳⍺), ⍳⍵Генерировать массивы от 1 до N и от 1 до K

    • ∘.{...}Для каждой пары элементов двух массивов примените функцию. Это дает матрицу числа переключений, каждый ряд представляет дверь, а каждый столбец представляет раунд.

    • +/Суммируйте столбцы. Это дает массив количества раз, когда каждая дверь переключается за все раунды.

    • 2|Модуль 2, поэтому, если дверь открыта, это 1; если он закрыт, это 0.

    • (...)/⍳⍺ Наконец, сгенерируйте массив от 1 до N и выберите только те, в которых есть 1 в массиве на предыдущем шаге.

  • /⎕ Наконец, вставьте функцию между числами из ввода.


РЕДАКТИРОВАТЬ

{(2|+⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕
  • ,↑⍳¨⍳⍵Генерация всех "обезьян" (если K = 4, то это 1 0 0 0 1 2 0 0 1 2 3 0 1 2 3 4)

    • ⍳⍵Массив от 1 до (K)

    • ⍳¨ Для каждого из них сгенерируйте массив от 1 до этого числа

    • ,↑Преобразовать вложенный массив в matrix ( ), а затем распаковать в простой array ( ,)

  • (,↑⍳¨⍳⍵)∘.|⍳⍺Для каждого числа от 1 до (N), модифицируйте его с каждой обезьяной.

  • 0=Измените на 1, где было 0, и 0 для всех остальных. Это дает матрицу переключений: строки - каждая обезьяна в каждом раунде, столбцы - двери; 1 означает переключение, 0 означает отсутствие переключения.

  • +⌿ Суммируйте строки, чтобы получить массив числа раз, когда каждая дверь переключена

Другие части не изменены


РЕДАКТИРОВАТЬ

{(≠⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕

Используйте XOR Reduce ( ≠⌿) вместо суммы и мод 2 ( 2|+⌿)


APL был разработан для сценария игры в гольф? ;-)
celtschk

@celtschk Да, частично, в некотором смысле. Он был разработан для краткого изложения алгоритмов.
luser droog

Почему вы используете уменьшение dfn {}/вместо того, чтобы просто принимать N и K в качестве аргументов для dfn?
Адам

@ Adám Потому что 1) это прошло мимо меня; 2) этот вопрос предшествует стандартизации "программы или функции" и ввода / вывода; 3) ОП специально сказал «разделены одним пробелом»
TwiNight

Справедливо, но, по крайней мере, вы можете сохранить байт с помощьюi←⍳⍺
Adám

4

GolfScript, 33 символа

~:k;),1>{0\{1$)%!k@-&^}+k,/}," "*

Если бы номера были пронумерованы, начиная с нуля, это спасло бы 3 символа.

Примеры ( онлайн ):

> 3 3
1 2

> 23 21
1 2 4 8 9 16 18 23

3

Mathematica, 104 символа

{n,k}=FromDigits/@StringSplit@InputString[];Select[Range@n,OddQ@DivisorSum[#,If[#>k,0,k+1-#]&]&]~Row~" "

Пример:

В [1]: = {n, k} = FromDigits / @ StringSplit @ InputString []; выберите [Range @ n, OddQ @ DivisorSum [#, If [#> k, 0, k + 1 - #] &] & ] ~ Row ~ ""

? 23 21

Out [1] = 1 2 4 8 9 16 18 23


1
Вы можете сбить еще 15 символов от разбора ввода, предположив входной поток, например: {n,k}=%~Read~{Number,Number}.
отмечает Томас

3

Руби, 88

Основано на ответе @ manatwork.

gets;~/ /
$><<(1..$`.to_i).select{|d|(1..k=$'.to_i).count{|m|d%m<1&&(k-m+1)%2>0}%2>0}*$&

Эти хитрые глобалы всегда нарушают подсветку синтаксиса!


Извините, но 90 символов ( версия 2 ) и 86 символов ( версия 3 ), кажется, глючат: в их результатах появилось новое число 22.
manatwork

@ Manatwork хороший вызов, я думаю, что я исправил это сейчас за счет двух символов. Я чувствую, что этот countбит мог бы быть улучшен и дальше, я бы хотел, чтобы у ruby ​​был встроенный #sumметод для таких вещей:>
Пол Престиж

Вот это да! Действительно впечатлен.
manatwork

3

Python 3, 97 84

Если обезьяна появляется в четном количестве раундов, это не меняет вообще. Если обезьяна появляется четное количество раз, это то же самое, что и в одном раунде.

Таким образом, некоторые обезьяны могут быть опущены, а другие просто должны поменять двери один раз.

N,K=map(int,input().split())
r=set()
while K>0:r^=set(range(K,N+1,K));K-=2
print(*r)

Выход для 23 21:

1 2 4 8 9 16 18 23

Умное использование операций над множествами! Я думаю, что вы можете сократить range(2-K%2,K+1,2)до range(K,0,-2).
xnor

Или еще лучше, замените forпетлю на whileпетлю:while K>0:r^=set(range(K,N+1,K));K-=2
xnor

@xnor: спасибо, это здорово!
Восстановить Монику

2

R - 74

x=scan(n=2);cat(which(colSums((!sapply(1:x[1],`%%`,1:x[2]))*x[2]:1)%%2>0))

Моделирование:

> x=scan(n=2);cat(which(colSums((!sapply(1:x[1],`%%`,1:x[2]))*x[2]:1)%%2>0))
1: 23 21
Read 2 items
1 2 4 8 9 16 18 23

2

JavaScript 148 127

function e(n,k){b=array(n);d=[];function a(c){for(i=0;i<n;i+=c)b[i]=!b[i];c<k&&a(c+1)}a(1);for(i in b)b[i]&&d.push(i);return d}

вот (крошечная) читаемая версия:

function e(n, k) {     //define N and K
     b = array(n); //declare all doors as closed
     d = [];     //create array later used to print results

     function a(c) {   //(recursive) function that does all the work
         for (i = 0; i < n; i += c)  //increment by c until you reach N and...
              b[i] = !b[i];  //toggle said doors
         c < k && a(c + 1)  //until you reach k, repeat with a new C (next monkey)
     }
     a(1); //start up A

     for (i in b) b[i] && d.push(i); //convert doors to a list of numbers
     return d //NO, i refuse to explain this....
}   //closes function to avoid annoying errors

ДЕМО скрипка

я должен отметить, что он начинает отсчитывать от 0 (технически это ошибка «один за другим»)


Вы можете удалить свою 3-ю строку, если вы измените 2-ю строку на b=Array(n);Это инициализирует ваш массив как длину n, заполненную неопределенным значением. ! undefined имеет значение true, поэтому первый проход обезьяны превратит все это в истины.
path411

@ path411 спасибо большое! я удивлен, я забыл, как работает "правильное" объявление массива! вы можете не стесняйтесь+1
Math Chiller

Интересный. Кажется, что вы единственный, кого я видел до сих пор, который, похоже, получил ответ, аналогичный моему, для N = 23, K = 21. Единственная разница заключается в том, что проблема «один за другим» включает 0 и 23.
Iszi

Разобрался, что не так с моим, а у этого такая же проблема. За каждый раунд вы посылаете только одну обезьяну через все двери. Однако, согласно спецификациям испытания, в каждом раунде должно быть $ i, где $ i - номер раунда, в котором вы участвуете.
Изи

2

JavaScript, 153

(function(g){o=[],f=g[0];for(;i<g[1];i++)for(n=0;n<=i;n++)for(_=n;_<f;_+=n+1)o[_]=!o[_];for(;f--;)o[f]&&(l=f+1+s+l);alert(l)})(prompt().split(i=l=s=' '))

Выход для N = 23, K = 21:

1 2 4 8 9 16 18 23  

Протестировано в Chrome, но не использует никаких новых интересных функций ECMAScript, поэтому должно работать в любом браузере!

Я знаю, что никогда не одержу победу над другими записями, и что @tiringToGetProgrammingStrainght уже отправил запись в JavaScript, но я не получил те же результаты для N = 23, K = 21, как и все остальные, поэтому я подумал, что хотел бы попробовать мою собственную версию.

Редактировать : аннотированный источник (просматривая это снова, я обнаружил места для сохранения еще 3 символов, так что это, вероятно, еще можно улучшить ...)

(function(g) {
    // initialise variables, set f to N
    o = [], f = g[0];

    // round counter
    // since ++' ' == 1 we can use the same variable set in args
    for (; i < g[1]; i++)
        // monkey counter, needs to be reset each round
        for (n = 0 ; n <= i; n++)
            // iterate to N and flip each Kth door
            for (_ = n; _ < f; _ += n + 1)
                // flip the bits (as undef is falsy, we don't need to initialise)
                // o[_] = !~~o[_]|0; // flips undef to 1
                o[_] = !o[_]; // but booleans are fine
    // decrement f to 0, so we don't need an additional counter
    for (;f--;)
        // build string in reverse order
        o[f] && (l = f + 1 + s + l); // l = (f + 1) + ' ' + l
    alert(l)
    // return l // use with test
// get input from user and store ' ' in variable for use later
})(prompt().split(i = l = s = ' '))
// })('23 21'.split(i = l = s = ' ')) // lazy...

// == '1 2 4 8 9 16 18 23  '; // test

хорошая работа! если бы вы также предоставили читаемую и прокомментированную версию, я бы, вероятно,+1
Math Chiller

Ответ обновлен! Поскольку я не могу прокомментировать ваш ответ, чтобы добавить к комментарию @ path411, вы можете установить b = [], и пустые индексы по-прежнему не определены, и это экономит вам еще 6 символов!
Дом Гастингс

я уже сделал это ...
математика чиллер

1

Рубин - 65 символов

(1..n).each{|d|
t=0
(1..k).each{|m|t+=n-m+1 if d%m==0}
p d if t%2>0}

n = 23, k = 21 # => 1 2 4 8 9 16 18 23 

Вот расчет в псевдокоде:

  • Пусть s (d) будет количеством раз, когда дверь d коснулась после k раундов.
  • s (d) = сумма (m = 1..m = k) (d% m == 0? (n-m + 1): 0)
  • дверь d открыта после k раундов, если s (d)% 2 = 1 (или> 0)

Если вы не уверены, что выражение для s (d) является правильным, посмотрите на это так:

  • Пусть s (d, r) будет количеством раз касаться двери d после r раундов.
  • s (d, k) - s (d, k-1) = сумма (m = 1, .., m = k) (d% m == 0? 1: 0)
  • s (d, k-1) - s (d, k-2) = сумма (m = 1, .., m = (k-1)) (d% m == 0? 1: 0)
  • ...
  • s (d, 2) - s (d, 1) = d% 2 == 0? 1: 0
  • s (d, 1) = 1
  • суммируйте обе стороны, чтобы получить вышеуказанное выражение для s (d), которое равно s (d, k)

Очень лаконично! Откуда nи kоткуда, правда? И вывод, кажется, разделен символами новой строки, а не пробелами.
Пол Престиж

1

PowerShell: 132

Гольф-код:

$n,$k=(read-host)-split' ';0|sv($d=1..$n);1..$k|%{1..$_|%{$m=$_;$d|?{!($_%$m)}|%{sv $_ (!(gv $_ -Va))}}};($d|?{(gv $_ -Va)})-join' '

Un-Golfed, прокомментированный код:

# Get number of doors and monkeys from user as space-delimited string.
# Store number of doors as $n, number of monkeys as $k.
$n,$k=(read-host)-split' ';

# Store a list of doors in $d.
# Create each door as a variable set to zero.
0|sv($d=1..$n);

# Begin a loop for each round.
1..$k|%{

    # Begin a loop for each monkey in the current round.
    1..$_|%{

        # Store the current monkey's ID in $m.
        $m=$_;

        # Select only the doors which are evenly divisible by $m.
        # Pass the doors to a loop.
        $d|?{!($_%$m)}|%{

            # Toggle the selected doors.
            sv $_ (!(gv $_ -Va))
        }
    }
};

# Select the currently open doors.
# Output them as a space-delimited string.
($d|?{(gv $_ -Va)})-join' '

# Variables cleanup - don't include in golfed code.
$d|%{rv $_};rv n;rv d;rv k;rv m;

# NOTE TO SELF - Output for N=23 K=21 should be:
# 1 2 4 8 9 16 18 23

О, я вижу, в чем моя проблема. Я неправильно понял вопрос - это не проблема 100 Локеров. Это так, занято на ступеньку выше! Это потребует немного больше работы ...
Iszi

1
Сладкий! Исправление этого, чтобы соответствовать требованиям испытания, принесло только 6 символов в конце.
Изи

0

Powershell, 66 байт

На основе Cary Swoveland в ответ .

param($n,$k)1..$n|?{$d=$_
(1..$k|?{($n-$_+1)*!($d%$_)%2}).Count%2}

Тестовый скрипт:

$f = {

param($n,$k)1..$n|?{$d=$_
(1..$k|?{($n-$_+1)*!($d%$_)%2}).Count%2}

}

@(
    ,(3, 3   , 1,2)
    ,(23, 21 , 1, 2, 4, 8, 9, 16, 18, 23)
) | % {
    $n,$k,$expected = $_
    $result = &$f $n $k
    "$("$result"-eq"$expected"): $result"
}

Выход:

True: 1 2
True: 1 2 4 8 9 16 18 23
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.