Найдите лишний в последовательности

20

Соревнование:

Рассмотрим функцию, F(N) = 2^N + 1где Nположительное целое число меньше, чем 31. Последовательность, определенная этой функцией:

3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097, 8193, 16385, 32769, 65537, 131073, 262145, 524289, 1048577, 2097153, 4194305, 8388609, 16777217, 33554433, 67108865, 134217729, 268435457, 536870913, 1073741825

Вход будет сгенерирован следующим образом:

  • Возьмите 5 смежных целых чисел из вышеуказанной последовательности.
  • Замените одно из них другим положительным целым числом (которое может быть или не быть частью вышеуказанной последовательности).
  • При желании можно изменить 5 полученных номеров.

Учитывая такой список из 5 целых чисел, найдите тот, который был заменен и, следовательно, не является частью оригинальных 5 смежных целых чисел.

Пример:

  • Оригинальный Подсписок: 5, 9, 17, 33, 65.
  • Заменить один: 5, 7, 17, 33, 65.
  • Упорядочивание 33, 17, 5, 7, 65.

Ожидаемый результат будет 7.

5 значений на входе всегда будут отличаться, и всегда будет уникальное решение. (Например, вам не придется иметь дело с входными данными, такими как, 3, 9, 17, 33, 129где либо, 3либо 129могли быть заменены.)

Тестовые случаи:

5,9,17,33,829
o/p: 829

9,5,17,829,33
o/p: 829

33, 17, 5, 7, 65
o/p: 7

5,9,177,33,65
o/p: 177

65,129,259,513,1025
o/p: 259

129,259,513,1025,65
o/p: 259

63,129,257,513,1025
o/p: 63

65,129,257,513,4097
o/p: 4097

5, 9, 2, 17, 33
o/p: 2

536870913, 67108865, 1073741825, 1, 268435457
o/p: 1
Аджай
источник
4
Для дальнейшего использования можно избежать путаницы и недопонимания, например, сначала опубликовать идеи испытаний в песочнице , где вы сможете получить обратную связь от сообщества, прежде чем люди начнут решать вашу задачу.
Мартин Эндер
@ Ajay Поскольку в спецификации все еще оставалось некоторое недоразумение, я еще раз отредактировал этот вызов, и, как мне кажется, вы были заинтересованы в этом вызове. Я надеюсь, что не ошибся, но дайте мне знать, если я ошибаюсь.
Мартин Эндер
@MartinEnder новый тестовый случай должен быть536870913,67108865,134217729,1,268435457
Йорг Хюльсерманн
@ JörgHülsermann Не стесняйтесь добавлять и это, но я намеревался добавить тестовый пример, охватывающий в N = 30качестве одного из входных значений.
Мартин Эндер
1
Интересная задача, потому что так легко придумать неправильные алгоритмы. И действительно, я никогда не видел так много неправильных ответов. Было бы еще хуже, если бы дубликаты были разрешены (многие методы, основанные на множестве (включая мой), потерпели бы неудачу)
Тон Хоспел

Ответы:

6

Желе, 15 байт

⁹R2*‘ṡ5ḟ@€µEÐfQ

TryItOnline
Все тестовые случаи также в TryItOnline

Возвращает список, содержащий один список, содержащий нечетный.

Как?

⁹R2*‘ṡ5ḟ@€µEÐfQ - Main link, a (list)
⁹               - literal 256 (saving a byte over literal 30)
 R              - range, [1,2,3,...]
  2*            - 2 ** x, [2,4,8,...]
    ‘           - increment, [3,5,9,...]
     ṡ5         - all contiguous slices of length 5
       ḟ@€      - filter with reversed arguments for each
          µ     - monadic chain separation
            Ðf  - filter on condition:
           E    - all equal (those previously filtered lists with only one value)
              Q - unique (there can be two, but both will have the same odd-one-out)
Джонатан Аллан
источник
5

JavaScript (ES6), 62 байта

a=>a.find(n=>--n&--n|!n)||a.sort((a,b)=>a-b)[a[0]*16>a[3]?4:0]

Абсолютно новый алгоритм, так как, как указывал @ edc65, предыдущий был сломан. Объяснение: Сначала мы разберемся с простым случаем, ища 2 или число, которое не на единицу больше, чем степень 2. Если ничего не найдено, то есть два возможных случая, в зависимости от того, было ли дополнительное значение ниже или выше исходный цикл из пяти, поэтому мы проверяем, принадлежат ли наименьшее и второе по величине значение к одному и тому же циклу из пяти, и в этом случае обвиняют самое большое значение, в противном случае самое маленькое значение.

Нил
источник
Почти нормально, но попробуйте n-1&n-2со значением2
edc65
@ edc65 не работает для [3, 17, 33, 65, 257].
Нил,
@ edc65 Хорошо --n&--n|!nвыглядит для 2дела?
Нил
Это выглядит действительно хорошо
edc65
4

Python, 84 байта

def f(a,i=0):s=set(a)-{2**j+1for j in range(i,i+5)};return len(s)<2and s or f(a,i+1)

Все тесты в идеале

Для корректного ввода возвращает набор, содержащий только odd-one-out.
Для неверного ввода будет достигнут предел рекурсии и будет выдана ошибка.

Джонатан Аллан
источник
4

Mathematica, 65 байт

f[a___,x_,b___]/;NestList[2#-1&,a~Min~b/. 2->0,4]~SubsetQ~{a,b}=x

Это определяет функцию, fкоторая должна вызываться с 5 аргументами, например

f[5, 9, 17, 33, 829]

В принципе, функцию можно вызывать с любым (ненулевым) числом аргументов, но вы можете получить неожиданные результаты ...

Я думаю, что это первый раз, когда мне удалось поместить все решение нетривиальной задачи в левую часть a =.

объяснение

Это решение действительно позволяет нам использовать возможности сопоставления с образцом Mathematica. Основная функция, которую мы используем, состоит в том, что Mathematica не может просто определять простые функции, как, f[x_] := (* some expression in x *)но мы можем использовать произвольно сложные шаблоны в левой части, например f[{a_, b_}, x_?OddQ] := ..., добавить определение, к fкоторому будет использоваться, только когда оно вызывается с двухэлементным список и нечетное целое число. Удобно, что мы уже можем давать имена элементам произвольно далеко вниз по левому выражению (например, в последнем примере мы могли бы сразу ссылаться на два элемента списка как aи b).

Шаблон, который мы используем в этой задаче f[a___,x_,b___]. Здесь a___и b___есть последовательности из нуля или более аргументов и xявляется одним аргументом. Так как правая часть определения просто x, что мы хотим, какая - то магия , которая гарантирует , что xиспользуется для ввода , мы ищем и a___и b___просто маски , которые охватывают остальные элементы.

Это делается путем прикрепления условия к шаблону с помощью /;. Правая часть /;(все до =) должна вернуться, Trueчтобы этот шаблон соответствовал. Прелесть в том , что модель согласовань Mathematica будет пытаться каждое назначение a, xи bк входам для нас, поэтому поиска правильного элемента делается для нас. По сути, это декларативное решение проблемы.

Что касается самого условия:

NestList[2#-1&,a~Min~b/. 2->0,4]~SubsetQ~{a,b}

Обратите внимание, что это не зависит xвообще. Вместо этого это условие зависит только от оставшихся четырех элементов. Это еще одна удобная особенность решения сопоставления с образцом: благодаря шаблонам последовательности aи bвместе содержат все другие входные данные.

Таким образом, это условие должно проверить, являются ли оставшиеся четыре элемента непрерывными элементами из нашей последовательности с не более чем одним пропуском. Основная идея для проверки этого состоит в том, что мы генерируем следующие четыре элемента из минимума (через ) и проверяем, являются ли четыре элемента его подмножеством. Единственные входные данные, в которых это может вызвать проблемы, - это те, которые содержат a , потому что это также генерирует допустимые элементы последовательности, поэтому нам нужно обрабатывать это отдельно.xi+1 = 2xi - 12

Последняя часть: давайте пройдемся по самому выражению, потому что здесь есть еще несколько забавных синтаксических символов.

...a~Min~b...

Эта инфиксная нотация коротка для Min[a,b]. Но помните, что aи bявляются последовательностями, так что это фактически расширяется до четырех элементов Min[i1, i2, i3, i4]и дает нам наименьший оставшийся элемент на входе.

.../. 2->0

Если это приводит к 2, мы заменяем его на 0 (который будет генерировать значения, которых нет в последовательности). Пространство необходимо, потому что иначе Mathematica анализирует плавающий литерал .2.

NestList[...&,...,4]

Мы применяем безымянную функцию слева 4 раза к этому значению и собираем результаты в список.

2#-1&

Это просто умножает его вход на 2 и уменьшает его.

...~SubsetQ~{a,b}

И, наконец, мы проверяем, что список, содержащий все элементы из aи bявляется подмножеством этого.

Мартин Эндер
источник
Я не знал, что Mathematica может сделать это!
DanTheMan
4

Ракетка 198 байт

(λ(m)(let((l(for/list((i(range 1 31)))(+ 1(expt 2 i))))(r 1)(n(length m)))(for((i(-(length l)n)))(let
((o(for/list((j m)#:unless(member j(take(drop l i)n)))j)))(when(eq?(length o)1)(set! r o))))r))

Безголовая версия:

(define f
  (λ(m)
    (let ((l (for/list ((i (range 1 31))) 
               (+ 1 (expt 2 i))))
          (res 1)
          (n (length m)))
      (for ((i (- (length l) n)))
        (let ((o (for/list ((j m) 
                             #:unless (member j 
                                             (take (drop l i) n))) 
                    j)))
          (when (eq? (length o) 1)
            (set! res o))))
      res)))

Тестирование:

(f '(5 9 17 33 829))
(f '(9 5 17 829 33))
(f '(5 9 177 33 65))
(f '(65 129 259 513 1025))
(f '(129 259 513 1025 65))
(f '(63 129 257 513 1025))
(f '(65 129 257 513 4097))

Выход:

'(829)
'(829)
'(177)
'(259)
'(259)
'(63)
'(4097)
rnso
источник
2

05AB1E , 32 30 26 24 20 байт

30Lo>Œ5ùv¹yvyK}Dgi`q

объяснение

30Lo>    # list containing the sequence [3 .. 1073741825]
Œ5ù      # all sequence sublists of length 5
v        # for each such list
 ¹yvyK}  # remove it's elements from input
 Dgi     # if the remaining list has length 1
    `q   # end the program and print the final list flattened

Попробуйте онлайн!

Emigna
источник
2

R, 97 байт

Это оказалось сложнее, чем я думал. Я уверен, что это может быть значительно лучше, хотя.

m=match(x<-sort(scan()),2^(1:31)+1);l=diff(m);ifelse(NA%in%m,x[is.na(m)],x[ifelse(l[4]>1,5,l>1)])

Разгромил и объяснил

x<-sort(scan())                  # read input from stdin and sort, store as vector
m=match(x, 2^(1:31)+1)           # generate a vector of indices for which input matches the sequence
l=diff(m)                        # vector of the difference of indices (will only contain 4 elements)
ifelse(NA%in%m,                  # if m contains NA do:
       x[is.na(m)],              # return x where no match has been found, else:
       x[ifelse(l[4]>1,5,l>1)])  # return x by index where diff>1 unless it's the last object, then return x[5]

match()Функция будет возвращать , NAесли какой - либо элемент входного вектора не в той последовательности , и , следовательно , мы можем просто найти индекс , где NAсуществуют на входе и вернуть это:x[is.na(m)]

Это становится немного сложнее, если ввод является частью последовательности, но не на месте. Поскольку входные данные были отсортированы, расстояние между каждой парой индексов должно быть 1. Поэтому мы можем найти неуместный элемент, исследуя 1stразницу в сопоставляемых индексах l=diff(m)и выбирая индекс, для которого l>1. Этого было бы достаточно, если бы не тот факт, что lсодержит 4элементы, а не 5. Это проблема только в том случае, если последний элемент в отсортированном входе является членом последовательности, НО не является частью подпоследовательности (как в последнем тестовом примере). Следовательно, если 4thэлемент >1извлекает 5thзапись в отсортированном вводе, в противном случае ищите индекс в 4векторе -length:x[ifelse(l[4]>1,5,l>1)]

Billywob
источник
1
в последних версиях R есть функция, anyNAкоторая эквивалентнаany(is.na(x))
JDL
2

Haskell, 66 64 байта

g x=[s|n<-[1..],[s]<-[filter(`notElem`[2^m+1|m<-[n..n+4]])x]]!!0

Пример использования: g [65,129,257,513,4097]-> 4097.

Перебирает все смежные подсписки длины 5 of F(N), сохраняет элементы, которых нет в списке ввода, xи шаблон соответствует элементам длины 1 (-> [s]).

Редактировать: @xnor сохранил два байта, удалив верхнюю границу внешнего цикла. Поскольку решение гарантировано существует, лень Haskell останавливается на первом найденном числе.

Ними
источник
Вам действительно нужна верхняя граница 26?
xnor
1

Perl, 64 59 байт

Включает +2 для -an

Дайте список ввода на STDIN:

perl -M5.010 oddout.pl <<< "5 9 2 17 33"

oddout.pl:

#!/usr/bin/perl -an
@a=grep$_,@a{@F,map{2**$_+++1}($.++)x5}=@F while$#a;say@a

Если вы не возражаете против переменного количества места вокруг результата, этот 58-байтный версон работает:

#!/usr/bin/perl -ap
$_=join$",@a{@F,map{2**$_+++1}($.++)x5}=@F while/\b +\b/

Обе версии зацикливаются навсегда, если вход не имеет решения.

Это очень больной код, но я не могу придумать ничего элегантного ...

%aНасколько я знаю, способ, которым я (ab) пользуюсь, - это новый трюк с perlgolf.

Тон Хоспел
источник
1

Python 2, 73 байта

s=set(input());i,=d={1}
while~-len(s-d):i*=2;d=d-{i/32+1}|{i+1}
print s-d

Перебирает наборы dиз пяти последовательных элементов последовательности до тех пор, пока не найдет элемент, содержащий все входные элементы, кроме одного, а затем напечатает разницу, которая является выходной информацией в единственном наборе.

Наборы dиз пяти последовательных элементов создаются из ничего путем многократного добавления нового элемента i+1и удаления любого старого элемента, i/32+1который находится перед текущим окном 5. Вот как выглядит его прогресс.

{1}
{3}
{3, 5}
{3, 5, 9}
{3, 5, 9, 17}
{3, 5, 9, 17, 33}
{5, 9, 17, 33, 65}
{9, 17, 33, 65, 129}
{17, 33, 65, 129, 257}
{33, 65, 129, 257, 513}

В начале инициализации находится паразитная единица, но она безвредна, потому что немедленно удаляется. Меньшие наборы, поскольку он собирает до 5 элементов, также безвредны.

XNOR
источник
1

PHP, 87 76 75 байт

for(;count($b=array_diff($argv,$a?:[]))-2;)$a[$n%5]=1<<++$n|1;echo end($b);

бежать с php -r '<code>' <value1> <value2> <value3> <value4> <value5>

Titus
источник
'a = [] `не является необходимым
Йорг Хюльсерманн
@ JörgHülsermann: Это необходимо для array_diff. Но я могу сохранить один байт там.
Тит
Это приводит к предупреждению array_diff (): Аргумент # 2 не является массивом. Хороший способ заполнить массив модом 5. Это спасет меня от массива и диапазона в моем предложении
Йорг Хюльсерманн
1
endвместо, maxи ваша заметка не более важна
Йорг Хюльсерманн
1

C #, 69 байт

int M(int[]a)=>a.Except(new int[30].Select((_,i)=>(1<<i+1)+1)).Sum();

Патрик Вестерлунд
источник
0

Java 7,85 байт

int f(int[]a,int l){int i=1;for(;i<l;)if(a[i++-1]*2-1!=a[i])return a[i];return a[0];}

Ungolfed

int f(int[]a,int l){
    int i=1;
    for(;i<l;)
    if(a[i++-1]*2-1!=a[i])
    return a[i];
   return a[0];

}
Numberknot
источник
Хм, ты уверен, что это работает правильно? Потому что я получаю неправильный вывод для тестовых случаев 1, 5, 6 и 7 (верны только второй, третий и четвертый вывод). Кроме того, параметр l31? В вопросе я вижу только массив int в качестве ввода, но не дополнительный int? : S
Кевин Круйссен
Не произойдет ли это, если нечетное значение будет вторым (с индексом 1)?
Тон Хоспель
Извините, ребята, я неверно истолковал вопрос. На самом деле, сейчас я нахожусь в больнице. Я изменю его за короткий промежуток времени.
Numberknot
0

PHP, 76 байт

реализовал идею Тита с модом 5

<?for(;count($x=array_diff($_GET[a],$r))-1;$r[++$i%5]=2**$i+1);echo end($x);

До 126 байт

<?for(;$x=array_diff($_GET[a],array_map(function($z){return 2**$z+1;},range(++$i,$i+4)));)if(count($x)<2){echo end($x);break;}
Йорг Хюльсерманн
источник
Функция анонимным: array_map(function($z){return 2**$z+1;},range($i,$i+4)). $x[key($x)]->end($x)
Тит
Положив 1-count($x=...)условие, вы избавитесь от перерыва: for(;1-count($x=...););echo end($x);(-13)
Титус
0

Pyth, 18 байт

hhlD-LQ.:mh^2dSCd5

Сформируйте последовательность, возьмите подсписки длиной 5, удалите каждый подсписок из Q, возьмите самый короткий результат, выведите его единственный элемент.

isaacg
источник
Не работает для[5, 9, 2, 17, 33]
Emigna
0

Котлин, 55 байт

fun f(a:IntArray)=a.find{it-1 !in(1..30).map{1 shl it}}

Патрик Вестерлунд
источник