Найти уникальных близнецов


28

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


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

A, B -> Выход

[6], [1, 6] -> 6
[1, 2, 3, 4], [4, 5, 6, 7] -> 4
[0, 73, 38, 29], [38, 29, 73, 0] -> 73
[1, 3, 4, 6, 6, 9], [8, 7, 6, 3, 4, 3] -> 4
[2, 2, 2, 6, 3, 5, 8, 2], [8, 7, 5, 8] -> 5
[12, 19, 18, 289, 19, 17], [12, 19, 18, 17, 17, 289] -> 289
[17, 29, 39, 29, 29, 39, 18], [19, 19, 18, 20, 17, 18] -> 17
[17, 29, 39, 29, 29, 39, 18, 18], [19, 19, 18, 20, 17, 18] -> 17

Ответы:


7

Желе , 7 байт

fċ@ÐṂ;Ṁ

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

Как это работает

fċ@ÐṂ;Ṁ  Main link. Left argument: A. Right argument: B

f        Filter; keep those elements of A that appear in B.
   ÐṂ    Yield all elements of the result for which the link to left yields a
         minimal value (2).
 ċ@        Count the occurrences of the element...
     ;     in the concatenation of A and B.
      Ṁ  Take the maximum.

7

Bash + coreutils, 49 байт

U()(sort -rn|uniq -u$1)
(U<<<$1;U<<<$2)|U D|sed q

Спасибо @seshoumara за отыгрывание 1 байта!

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

Как это работает

uniq принимает отсортированный ввод и выполняет одно или несколько действий, в зависимости от флагов командной строки.

U<<<$1и U<<<$2вызвать функцию Uс первым и вторым аргументом командной строки в качестве входных данных. Для каждого из sort -rn|uniq -uних выполняется сортировка ввода по номерам ( -n) и в порядке убывания ( -r) для uniq , который будет печатать только уникальные строки ( -u).

Выход обоих (уникальных элементов каждого массива) объединяется и конвейеру U D, то есть
sort -rn|uniq -uD. На этот раз uniq будет печатать только дубликаты строк ( -D) и только первое повторение каждой из них.

Хотя на странице руководства написано, что будут напечатаны все повторы, добавленные -uпричины -Dбудут печатать только первое появление дублированных строк. Такое поведение обычно достигается с uniq -d.

Наконец, sed qнемедленно завершает работу, сокращая ввод (уникальные элементы обоих массивов) до первой строки. Поскольку выходные данные были отсортированы в порядке убывания, это максимум.


6

Pyth, 12 9 байтов

Попытайся

eS@Fm.m/d

Сохранено 3 байта благодаря г-ну Xcoder.

объяснение

eS@Fm.m/d
    m  /d   Count the occurrences of each element.
     .m     Take only those that appear the minimum number of times.
  @F        Apply the above to A and B and take the intersection.
eS          Take the largest.

Ницца! Мое решение было также 12 байтов .
Мистер Xcoder

Разверните мое решение немного, 9 байтов (используя eS@Fm.m/d) и взяв входные данные в виде списка из двух списков.
г-н Xcoder

@ Mr.Xcoder Это кажется другим, чтобы быть его собственным ответом.

Поскольку я являюсь ФП конкурса, я не хочу его публиковать. Вы можете просто использовать его и отдать должное, упомянув свой текущий подход в качестве альтернативы (если хотите, конечно)
Mr. Xcoder



5

Шелуха , 7 байт

→►≠OfEΠ

Принимает ввод в виде списка из двух списков, работает также для любого количества списков (возвращая наибольшее число, которое встречается ровно один раз в каждом, если это возможно). Попробуйте онлайн!

объяснение

Это первый ответ Husk на (ab) использование новой функции «Maximum by» .

→►≠OfEΠ  Implicit input, say [[3,2,1,3],[1,2,3,4]]
      Π  Cartesian product: [[3,1],[2,1],[3,2],[2,2],[1,1],[3,3],[1,2],[3,1],[3,4],[2,3],[1,3],[3,2],[2,4],[3,3],[1,4],[3,4]]
    fE   Keep those that have equal elements: [[2,2],[1,1],[3,3],[3,3]]
   O     Sort: [[1,1],[2,2],[3,3],[3,3]]
 ►≠      Find rightmost element that maximizes number of other elements that are not equal to it: [2,2]
→        Take last element: 2

4

Bash + coreutils, 60 байт

f()(sort -rn<<<"$1"|uniq -u);grep -m1 -wf<(f "$1") <(f "$2")

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

Баш, 89 байт

c()(for e;{((e^$1||r++,2^r));});for x in $1 $2;{((x<r))||c $x $1||c $x $2||r=$x;};echo $r

TIO


1
Используйте sort -rnс sed qв конце вместо того, tail -1чтобы побрить 1 байт. Отличная находка с grep -wfкстати. +1
сешумара

@seshoumara, спасибо за совет, на самом деле я могу побрить 3 байта с опцией -m1 grep.
Науэль Фуйе


3

J, 23 байта

>./@([-.-.)&(-.-.@~:#])

(-.-.@~:#]) удаляет из списка любые повторяющиеся элементы

& сделать это с обеими аргументами

([-.-.) Мы хотим, чтобы A пересекалось с B. Это эквивалентная фраза: «A минус (A минус B)»

>./ Взять максимум

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


Эквивалентно, вы можете заменить часть пересечения на e.~#]. Гольф это оказалось непростым делом ... Я пытался использовать /.-key безуспешно ( ((1=#)/.~#~.)для первой части, которая, по моим подсчетам, на 2 байта длиннее)
Коул

@cole, да, я тоже попробовал ключевой подход, а также метод самоклассификации. Я не смог превзойти мои представления выше с любым другим подходом, хотя.
Иона

2

PowerShell , 94 байта

param($a,$b)filter f($x){$x|group|?{$_.count-eq1}}
(f($a|sort|?{$_-in((f $b).Name)}))[-1].Name

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

Берет вход $aи $bкак массивы. Создает , filterчто groupев элементы входного массива вместе и вытаскивает только те , с count -eqUAL к 1(то есть, только те , которые являются уникальными во входном массиве).

Следующая строка затем строит алгоритм. Сначала мы sort $a, а затем вытащить те, которые являются -inуникальными предметами $b. Они сами тогда уникальны, [-1]выбирается самое большое , и мы берем .Nameих. Это осталось на конвейере и вывод неявный.


2

Javascript (ES6), 102 86 75 71 байт

a=>b=>Math.max(...a.map(e=>(g=x=>x.map(y=>y-e||x--,x=1)|!x)(a)*g(b)*e))

Спасибо @justinMariner за получение от 102 до 86

Спасибо @tsh за получение от 86 до 75

Спасибо @Arnauld для получения от 75 до 71

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


Добро пожаловать в PPCG! Насколько я могу судить, это не гарантирует, что это eпоявляется только один раз aи b.
Мартин Эндер

@MartinEnder Спасибо! Отредактировал ответ, чтобы отразить детали, которые я пропустил!
Nate

1
Я никогда не думал использовать lastIndexOfэто, это довольно умно. Вы можете получить это до 86 байт: попробуйте онлайн! , Проверьте советы JS для больше.
Джастин Маринер

1
Кажется, что использование (g=x=>x.filter(y=>y==e).length==1)короче.
TSH

1
Я думаю, что этот также проходит все крайние случаи (71 байт).
Арно

2

Haskell , 57 53 байта

x?y|let v!x=filter(==v)x==[v]=maximum[a|a<-x,a!x,a!y]

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

UPD: спасибо @Laikoni


Добро пожаловать в PPCG и Haskell в гольф в частности! Это хороший первый ответ! Две маленькие вещи: Вы также можете объявить fкак инфиксный оператор и написать [1|...]==[1]вместо того, sum[1|...]==1чтобы сохранить несколько байтов
Лайкони

Если вы еще не видели их, вот несколько ссылок, которые могут быть интересны: наша коллекция советов по игре в гольф на Хаскелле , руководство по правилам игры в гольф на Хаскелле и « Монады и мужчины» , наш чат на Хаскелле.
Лайкони

1
Встраивание !с andэкономит еще два байта: попробуйте онлайн!
Лайкони

2

Wolfram Language (Mathematica) , 40 байт

Max@Cases[Tally@#⋂Tally@#2,{x_,1}:>x]&

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

Как это работает

Tally@#дает список уникальных элементов первого ввода вместе с их количеством: например, Tally[{2,2,2,6,3,5,8,2}]доходность {{2,4},{6,1},{3,1},{5,1},{8,1}}.

Tally@#2делает то же самое для второго списка и находит пары, присутствующие в обоих. Затем мы выбираем (с Cases) пары, оканчивающиеся на 1, беря первый элемент каждого результата, что дает нам список всех уникальных близнецов. Наконец, Maxвозвращается самый большой уникальный близнец.


2

Рёда , 48 байт

{m={|n|sort|count|[_]if[_=n]};[_()|m 1]|m 2|max}

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

Вдохновленный ответом jq170727's jq .

Объяснение:

{ /* Anonymous function, takes input from the stream */
  m={|n|        /* Local function m with parameter n: */
    sort|count| /*   Count unique values in the stream */
    [_]if[_=n]  /*   For each value, push it to the stream if its count is n */
  };
  [      /* For each list in the stream: */
    _()| /*   Flat it (push its values to the stream) */
    m 1  /*   Push values that appear only once to the stream */
  ]|
  m 2|   /* Push values that appear twice to the stream */
  max    /* Find the max value in the stream */
}

2

F # (.NET Core) , 117 115 114 111 108 байт

115 114 байт

Другое решение с countByэтим временем:

let u x=x|>Seq.countBy id|>Seq.filter(fun a->snd a=1)|>Seq.map fst|>set
let f x y=Set.intersect(u x)(u y)|>Seq.max

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

117 111 байт

let u x=x|>Seq.filter(fun a->x|>Seq.filter((=)a)|>Seq.length=1)|>set
let f x y=Set.intersect(u x)(u y)|>Seq.max

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

100% F #! Любая помощь приветствуется!

6 байтов выиграно благодаря префиксной нотации!

108 байт

let f a b=Set.intersect(set a)(set b)|>Seq.filter(fun x->a@b|>Seq.filter(fun y->y=x)|>Seq.length<3)|>Seq.max

@это функция concat! Спасибо @ Ayb4btu за этот алгоритм.

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



2

Пип , 17 16 байт

MX{_Na=_Nb=1FIa}

Эта функция принимает два списка в качестве аргументов. Попробуйте онлайн!

объяснение

  {            }  Define function, args are a & b:
            FIa    Filter elements of a on this function:
   _Na              Count of element in a
      =_Nb          equals count of element in b
          =1        equals 1
                  This gives a function that returns a list of unique twins
MX                Modify it to take the max and return that instead

2

APL (Dyalog) , 18 символов = 23 байта *

Полное тело программы. Запрашивает список списков из STDIN. Работает с любым количеством списков. Выходы в STDOUT.

⌈/∊∩/{⊂⍺⍴⍨1=≢⍵}⌸¨⎕

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

 запросить оценку ввода от STDIN

{}⌸¨ Для каждого списка вызовите следующую функцию для каждого уникального элемента в этом списке, используя уникальный элемент в качестве левого аргумента ( ) и список индексов его появления в качестве правого аргумента ( ):

≢⍵ подсчет индексов (т.е. количество вхождений)

1= равно 1

⍺⍴⍨ используйте это, чтобы изменить форму определенного элемента (т.е. дает пустой список, если не уникален)

Теперь у нас есть два списка уникальных элементов для каждого входного списка (хотя каждый элемент является списком, и есть пустые списки как остаток от неуникальных элементов).

∩/ пересечение (сокращение)

ε NLIST (Flatten)

⌈/ Макс (уменьшение)


* в Классике, считая как ⎕U2338.


1

MATL , 13 байт

,iSY'1=)]X&X>

Попробуйте онлайн! Или проверьте все контрольные примеры .

объяснение

,      % Do twice
  i    %   Take input: array
  S    %   Sort array
  Y'   %   Run-length encode: pushes array of values and array of run lengths
  1=   %   Compare each run length with 1
  )    %   Use as logical index. This keeps only values that have appeared once
]      % End
X&     % Intersection of the two arrays
X>     % Maximum of array. Implicitly display

1

PHP, 98 байт

<?foreach(($c=array_count_values)($_GET[a])as$a=>$n)$n-1||$c($_GET[b])[$a]-1||$a<$r||$r=$a;echo$r;

Предоставить массивы в качестве параметров GET aи b.


Думаю, вы могли бы поменять эти GET-параметры на константы.
Progrock

@Progrock Это не допустимый метод ввода.
Тит

Вопрос формулирует, что A и B даны как массивы. И говорит любой разумный метод ввода и вывода .... не то, чтобы я мог легко перейти по этой ссылке. Очень нравится твой рецепт. (Дроссели в устаревшем Php 5.6 хотя.)
Progrock

1

Java 8, 133 байта

a->b->{long r;for(java.util.Collections c=null;;a.remove(r))if(b.contains(r=c.max(a))&c.frequency(a,r)*c.frequency(b,r)==1)return r;}

Объяснение:

Попробуй это здесь.

a->b->{                  // Method with two ArrayList<Long> parameters and long return-type
  long r;                //  Result-long
  for(java.util.Collections c=null; 
                         //  Create a java.util.Collections to save bytes
      ;                  //  Loop indefinitely
       a.remove(r))      //    After every iteration, remove the current item
    if(b.contains(r=c.max(a)) 
                         //   If the maximum value in `a` is present in `b`,
       &c.frequency(a,r)*c.frequency(b,r)==1)
                         //   and this maximum value is unique in both Lists:
      return r;          //    Return this value
                         //  End of loop (implicit / single-line body)
}                        // End of method

1

R , 73 байта

function(A,B)max(setdiff(intersect(A,B),c(A[(d=duplicated)(A)],B[d(B)])))

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

Вычисления Aпересекаются B, тогда максимум разницы между этим и дублированными элементами Aи B.


1

JavaScript ES5, 122 121 114 байт

function f(a,b){for(i=a.sort().length;--i+1;)if(a[i]!=a[i+1]&&a[i]!=a[i-1]&&!(b.split(a[i]).length-2))return a[i]}

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

Вот рабочий пример: 122 121 114

От 122 до 121 байта: инициализация переноса в

От 121 до 114 байт: bдолжна быть строка


2
Добро пожаловать в PPCG! Вы не можете удалить определение функции, но вместо этого вы можете использовать лямбда-функцию (я не знаю JS, поэтому не могу вам с этим помочь).
мистер Xcoder

Спасибо за очистку этого. Я не думаю, что лямбда-функции могут сохранять любые символы, но я попробую. Кроме того, поскольку вы говорите: «Разрешен любой разумный метод / формат ввода и вывода», могу ли я принять строку как bи сохранить b=''+b,?
Piyin

Мне удалось получить до 115 байт , хотя я не знаю , JavaScript: f=(a,b)=>{for(b=''+b,i=a.sort().length;--i+1;)if(a[i]!=a[i+1]&&a[i]!=a[i-1]&&!(b.split(a[i]).length-2))return a[i]}.
Mr. Xcoder

1
Да, уверен, что ввод строки будет хорошо
г-н Xcoder

Но тот JavaScript, который вы создали, будет ES5, а не ES6. Ответ ES6 уже опубликован, поэтому я разместил ES5. И спасибо, что
ответили


1

Jq 1,5 , 76 байт

def m(n):[.[indices(.[])|select(length==n)[]]]|unique[];[map(m(1))|m(2)]|max

расширенный

def m(n): # function to emit elements of multiplicity n
  [
    .[                         # select elements with
         indices(.[])          # number of indices in the array
       | select(length==n)[]   # equal to specified multiplicity
    ]
  ] | unique[]                 # emit deduped values
;

[
    map(m(1))   # collect multiplicity 1 elements from each array
  | m(2)        # collect multiplicity 2 elements
] | max         # choose largest of these elements

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

Вот еще одно решение такой же длины:

def u:[keys[]as$k|[.[$k]]-(.[:$k]+.[$k+1:])]|add;map(u)|.[0]-(.[0]-.[1])|max

расширенный

def u: # compute unique elements of input array
  [
      keys[] as $k                   # for each index k
    | [.[$k]] - (.[:$k]+.[$k+1:])    # subtract other elements from [ .[k] ]
  ]                                  # resulting in [] if .[k] is a duplicate
  | add                              # collect remaining [ .[k] ] arrays
;
  map(u)                             # discard duplicates from each input array
| .[0]-(.[0]-.[1])                   # find common elements using set difference
| max                                # kepp largest element

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


1

APL, 47 байт

{1↑R[⍒R←((1={+/⍵=A}¨A)/A←⍺)∩(1={+/⍵=B}¨B)/B←⍵]}

Объявляет анонимную функцию, которая принимает два вектора, удаляет дубликаты элементов, а затем находит самый большой элемент в пересечении результатов.

A←⍺и B←⍵сохраните аргументы, переданные функции в Aи B.

a=bвозвращает вектор с 1 в каждом индексе, в котором aравно b. Если aскаляр (т.е. единичная величина, а не вектор), это возвращает вектор с 1, где элемент bнаходится, aи 0, когда это не так. Например:

Input: 1=1 2 3
Output: 1 0 0

{+/⍵=A}: вложенная анонимная функция; найти вхождения аргумента в вектореA и сложить их, т.е. найти количество вхождений аргумента вA

1={+/⍵=A}¨A: примените вложенную анонимную функцию к каждому элементу в A и найдите те, которые равны 1, т.е. уникальные элементы

((1={+/⍵=A}¨A)/A←⍺): найдя расположение уникальных элементов, выберите только эти элементы в исходном векторе (/ выбирает из правого аргумента элементы, расположение которых соответствует 1 в левом аргументе)

R←((1={+/⍵=A}¨A)/A←⍺)∩(1={+/⍵=B}¨B)/B←⍵: повторить процесс для второго аргумента; Теперь, когда у нас есть только уникальные элементы, найдите пересечение, т.е. общие элементы, и сохраните его в вектореR

R[⍒R]: доступ к элементам R в порядке убывания

1↑R[⍒R]: взять первый элемент R сортировки в порядке убывания

Прецедент:

Input: 17 29 39 29 29 39 18 18 {1↑R[⍒R←((1={+/⍵=A}¨A)/A←⍺)∩(1={+/⍵=B}¨B)/B←⍵]} 19 19 18 20 17 18
Output: 17

1

J , 30 байт

[:>./@,[*([*+/"1(1=*/)+/)@(=/)

Как это работает:

Я начинаю с тестирования, где два списка перекрываются =/(вставляет тест на равенство между всеми членами списков:

   a =. 1 3 4 6 6 9
   b =. 8 7 6 3 4 3
   ]c=. a =/ b 
0 0 0 0 0 0
0 0 0 1 0 1
0 0 0 0 1 0
0 0 1 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0

Более одного 1 в одном и том же столбце означает, что число не является уникальным для левого аргумента (в данном случае 6); в строке - для правильного аргумента (3)

Затем я суммирую все строки и все столбцы, чтобы найти, где находятся дубликаты:

   +/ c
0 0 2 1 1 1
   +/"1 c
0 2 1 1 1 0

Я нахожу декартово произведение вышеупомянутых списков и устанавливаю элементы больше 1 к 0.

    m =. (+/"1 c) (1=*/) +/c
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 1 1 1
0 0 0 1 1 1
0 0 0 1 1 1
0 0 0 0 0 0

Я маскирую матрицу равенства c с помощью m, чтобы найти уникальные элементы, общие для обоих списков, и умножаю левый аргумент на это.

]l =. a * m * c
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 4 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

Затем я выравниваю список и нахожу элемент max:

 >./,l 
4

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


1

C # (.NET Core) , 66 + 31 = 97, 65 + 31 = 96 байт.

a=>b=>a.Intersect(b).Where(x=>a.Concat(b).Count(y=>y==x)<3).Max()

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

+31 байт для using System;using System.Linq;

Я черпал вдохновение из ответа @ aloisdg. Однако вместо того, чтобы искать уникальные значения в обоих массивах, я инвертировал порядок операций, так что intersectсначала, а затем нахожу максимальное значение элементов, которые встречаются дважды, когда массивы сцепляются и пересекаются. Я могу использовать <3какCount будет по крайней мере 2 для любого значения, как это будет в обоих массивах.

Подтверждения

-1 байт благодаря @aloisdg и его предложению использовать Funcкарри.


1
Хорошая идея! Мне действительно это нравится
aloisdg говорит восстановить Monica



0

Октава , 57 56 байт

@(x)max(intersect(cellfun(@(x){x(sum(x'==x)==1)},x){:}))

Анонимная функция, которая принимает в качестве входных данных массив ячеек из двух числовых массивов.

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

объяснение

Для каждого ( cellfun(@(x)...)) из двух входных массивов это создает матрицу парных сравнений равенства между его записями ( x.'==x); сохраняет ( x(...)) только те записи, для которых сумма столбца равна 1( sum(...)==1); и упаковывает результат в ячейку ( {...}). Пересечение ( intersect) двух результатов ( {:}) вычисляется, и max(...)берется максимум ( ).


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.