Найдите недостающее письмо


27

Руководящие указания

задача

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


правила

  • Это код гольф, поэтому выигрывает самый короткий ответ в байтах!
  • Вы всегда получите правильный массив
  • Всегда будет отсутствовать ровно одна буква
  • Длина массива всегда будет не менее 2.
  • Массив всегда будет содержать буквы только в одном регистре (в верхнем или нижнем регистре)
  • Вы должны вывести в том же регистре (в верхнем или нижнем регистре), что ввод
  • Массив всегда будет идти только одна буква за раз (пропуская пропущенную букву)
  • Длина массива будет между 2 и 25
  • Первый или последний элемент массива никогда не будет отсутствовать

Примеры

['a','b','c','d','f'] -> 'e'

['O','Q','R','S'] -> 'P'

['x','z'] -> 'y'

['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','w','x','y','z'] -> 'v'


Могу ли я взять строку вместо?
Дрянная Монахиня

@LeakyNun Строки - это массивы символов, так что да.
Аморрис

1
Может ли вывод быть массивом, содержащим отсутствующий символ (например: для ввода ['a','b','c','d','f','g'], вывода ['e'], если это делает код короче?
Mr. Xcoder

1
@ Mr.Xcoder Строка - это просто массив символов, так что да
Amorris

2
Четвертое правило является просто подмножеством восьмого правила и может быть удалено (по крайней мере, если вы поставите слово «включительно» в конце восьмого правила).
НХ.

Ответы:



11

C # (.NET Core) , 48 47 46 байтов, ввод в виде массива символов

s=>{for(int i=0;s[++i]==++s[0];);return s[0];}

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

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

C # (.NET Core) , 58 56 50 байт, ввод в виде строки

s=>{var c=s[0];while(s.IndexOf(++c)>=0);return c;}

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

Предыдущее 58-байтовое решение (упомянутое в первом комментарии):

s=>{for(int i=1;;i++)if(s[i]-s[0]>i)return(char)(s[i]-1);}

Алгоритмы с использованием System.Linq

Следующие алгоритмы должны добавить using System.Linq;(18 байт) к числу байтов и, следовательно, длиннее.

Мне очень понравился этот (52 + 18 байт):

s=>{int i=0;return(char)(s.First(c=>c-s[0]>i++)-1);}

И у вас также есть однострочное (45 + 18) -байтное решение:

s=>(char)(s.Where((c,i)=>c-s[0]>i).First()-1)

И очень умное (37 + 18) -байтовое решение, любезно предоставленное Ed'ka:

s=>s.Select(e=>++e).Except(s).First()

1
Не скомпилируется ли это, не все пути кода возвращают значение? Но +1 для сравнения с s[i]-s[0], довольно умно!
TheLethalCoder

@TheLethalCoder Это не приведет к сбою, так как forцикл не имеет условия остановки, поэтому он будет повторяться до тех пор, пока ifусловие не будет выполнено true.
Чарли

1
Вы можете сохранить 8 байтов следующим образом: a=>{int i=0;for(;a[++i]-a[0]<=i;);return--a[i];}(когда вы принимаете ввод как char[]). Не благодаря мне, кстати, благодаря комментарию @Nevay к моему ответу на Java 8 .
Кевин Круйссен

1
@KevinCruijssen нашел способ сохранить еще два байта, используя входные данные как массив символов.
Чарли

1
Более короткая версия Linq:s=>s.Select(e=>++e).Except(s).First()
Ed'ka

8

Алиса , 10 байт

/X.
\ior@/

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

объяснение

Это просто структура для линейных программ, которые работают полностью в обычном режиме (обработка строк):

/...
\.../

Фактический линейный код тогда:

i.rXo@

Который делает:

i   Read all input.
.   Duplicate.
r   Range expansion. If adjacent letters don't have adjacent code points, the
    intermediate code points are filled in between them. E.g. "ae" would turn
    into "abcde". For the inputs in this challenge, this will simply insert
    the missing letter.
X   Symmetric set difference. Drops all the letters that appear in both strings,
    i.e. everything except the one that was inserted by the range expansion.
o   Output the result.
@   Terminate the program.



7

Java 8, 70 57 56 48 46 байт

a->{for(int i=0;++a[0]==a[++i];);return a[0];}

-14 (70 → 56) и -2 (48 → 46) байтов благодаря @CarlosAlejo .
-8 (56 → 48) байтов благодаря @Nevay .

Объяснение:

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

a->{            // Method with char-array parameter and char return-type
  for(int i=0;  //  Start index-integer at 0 and loop as long as
    ++a[0]      //   the previous character + 1 (by modifying the character at index 0)
    ==a[++i];   //   equals the next character (by raising the index by 1 before checking)
  );            //  End of loop
  return a[0];  //  Return the now modified character at index 0 in the array
}               // End of method

1
Вы можете использовать неявное приведение вместо явного преобразования для сохранения 8 байтов a->{int i=0;for(;a[++i]-a[0]<=i;);return--a[i];}.
Невай

6

C (gcc) , 3335 36 48 60 байтов

Все оптимизации должны быть отключены и только на 32-битном GCC.

f(char*v){v=*v+++1-*v?*v-1:f(v);}

Принять ввод как строку.

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


2
«Все оптимизации должны быть отключены и только на 32-битном GCC». очень окольный способ сказать, что это не работает (кажется, работает только из-за UB)
сехе

Я бы сказал foo(char*a){return*a+1==a[1]?foo(a+1):++*a;}, очень хорошо; Только на 1 символ короче, чем более естественныйfoo(char*a){while(*a+1==a[1])a++;return++*a;}
сехе

@sehe постоянное неопределенное поведение считается приемлемым на PPCG
Кейу Ган

5

Python 3 , 74 62 58 44 40 байт

-12 байтов благодаря Эрику Аутгольферу. -18 байт благодаря Лики Нун. -4 байта благодаря musicman523.

Принимает ввод как строку байта.

lambda s:chr(*{*range(s[0],s[-1])}-{*s})

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

Еще одно крутое решение:

lambda s:chr(*{*range(*s[::~-len(s)])}-{*s})

1
.difference({*s})->-{*s}
Эрик Outgolfer




1
Ваше решение - то, к чему я
стремился,

4

Mathematica, 46 байт

Min@Complement[CharacterRange@@#[[{1,-1}]],#]&

Я считаю, что Min@Complement[CharacterRange@@#[[{1,-1}]],#]&это спасло бы байт.
LegionMammal978

@ LegionMammal978 на самом деле 2!
J42161217

3

JavaScript (ES6), 70 байт

Ввод в виде массива символов

(a,p)=>a.some(c=>(q=p+1,p=c.charCodeAt(),p>q))&&String.fromCharCode(q)

Меньше гольфа

a=>{
  p = undefined;
  for(i = 0; c = a[i]; i++)
  {
    q = p+1
    p = c.charCodeAt()
    if (p>q)
      return String.fromCharCode(q)
  }
}

Тест

F=(a,p)=>a.some(c=>(q=p+1,p=c.charCodeAt(),p>q))&&String.fromCharCode(q)

function update() {
  var a0=A0.value.charCodeAt()
  var a1=A1.value.charCodeAt()
  if (a1>a0) {
    var r = [...Array(a1-a0+1)]
      .map((x,i)=>String.fromCharCode(a0+i))
      .filter(x => x != AX.value)
    I.textContent = r.join('') + " => " + F(r)
  }
  else {
    I.textContent=''
  }
}

update()
input { width: 1em }
Range from <input id=A0 value='O' pattern='[a-zA-Z]' length=1 oninput='update()'>
to <input id=A1 value='T' pattern='[a-zA-Z]' length=1 oninput='update()'>
excluding <input id=AX value='Q' pattern='[a-zA-Z]' length=1 oninput='update()'>
<pre id=I></pre>



3

Сетчатка , 33 25 байт

$
¶$_
T`p`_p`.*$
D`.
!`.$

Попробуйте онлайн! Работает с любым диапазоном символов ASCII. Изменить: Сохранено 8 байт благодаря @MartinEnder. Объяснение: Первый этап дублирует ввод. Вторая уменьшает все символы в копии на 1 кодовую точку. На третьем этапе удаляются все символы в копии, которые все еще появляются в оригинале. Это просто оставляет исходный ввод, символ, который предшествует первому символу исходного ввода и пропущенный символ. Последняя стадия просто соответствует отсутствующему символу.


Вот 25 с использованием той же основной идеи: tio.run/##K0otycxL/P9fhevQNpV4rpCEgoT4ggQ9LRUulwQ9LsUEPZX///… (я уменьшаю вторую строку, потому что это сохраняет байт, а затем я нахожу уникальный символ с использованием дедупликации.)
Мартин Эндер

@MartinEnder Дедупликация - это именно то, что я хотел все время, и я уже забыл, что у Retina она есть, вздох ... (Я знаю, что увеличение первой строки занимает байт больше, чем уменьшение второй строки, но это сделало регулярное выражение соответствия короче.)
Нейл

3

SWI Пролог, 124 байта

m([H|T]):-n(H,N),c(T,N),!,m(T).
n(I,N):-o(I,C),D is C+1,o(N,D).
c([N|_],N).
c(_,N):-print(N),!,fail.
o(C,O):-char_code(C,O).

Примеры:

?- m(['a','b','c','d','f']).
e
false.

?- m(['O','Q','R','S']).
'P'
false.

?- m(['x','z']).
y
false.

?- m(['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','w','x','y','z']).
v
false.

Маленькое объяснение:

Это mосновная процедура, которая nпроизводит следующий ожидаемый символ в списке. cДелает сравнение - если ожидания соответствуют следующему пункту, продолжайте, иначе распечатать ожидаемый характер и выпрыгнуть из окна.


1
Короче fail: 0=1.
мат

3

C ++ 14, стандартная библиотека, универсальный тип контейнера ( 87 86 байт)

[](auto a){return++*adjacent_find(begin(a),end(a),[](auto a,auto b){return a+1!=b;});}

::stdПредполагается тип контейнера из пространства имен (например std::string, std::listили std::vector. В противном случаеusing namespace std; или аналогичным образом предполагается).

Благодаря @Ven, с небольшим взломом препроцессора, вы получите его до 82 байт (1 перевод строки)

#define x [](auto a,int b=0){return++
x *adjacent_find(begin(a),end(a),x a!=b;});}

Видеть это Live On Coliru

C ++ 14 без стандартной библиотеки (все еще универсальный, 64 63 байта)

[](auto& a){auto p=*begin(a);for(auto c:a)if(c!=p++)return--p;}

Опять же, нужно помочь поиску имени, только если тип контейнера не из пространства имен ::std(или связан с ним)

Live On Coliruдля , std::stringнапример ,

Live On Coliruдля , char const[]например ,


Вам нужно поставить пробел между зачеркнутым текстом и следующим текстом.
CJ Деннис

@CJDennis Готово. Кстати, ваша текущая репутация (2469) - это красивое число (3 * 823, а также визуально в паре как (24) (69), которое (2 2 2 3) (3 23))
сехе


2

C #, 104 байта

using System.Linq;a=>(char)Enumerable.Range(a.Min(),a.Max()-a.Min()).Except(a.Select(c=>(int)c)).First()

Полная / Отформатированная версия:

using System.Linq;

namespace System
{
    class P
    {
        static void Main()
        {
            Func<char[], char> f = a =>
                (char)Enumerable.Range(a.Min(), a.Max() - a.Min())
                                .Except(a.Select(c=>(int)c))
                                .First();

            Console.WriteLine(f(new[] { 'a', 'b', 'c', 'd', 'f' }));

            Console.ReadLine();
        }
    }
}

Очень умная версия Linq от Ed'ka :s=>s.Select(e=>++e).Except(s).First()
Чарли

@CarlosAlejo Я видел, как вы добавили его в свой ответ, поэтому я не буду обновлять мой, но да, это очень умно. Намного короче, чем моя версия.
TheLethalCoder

2

MATL, 8 7 байт

1 байт сохранен благодаря @Luis

tdqf)Qc

Попробуйте это на MATL Online

объяснение

      % Implicitly grab the input as a string
t     % Duplicate the string
d     % Compute the differences between successive characters
q     % Subtract 1 from each element
f     % Get the locations of all non-zero characters (1-based index)
)     % Extract that character from the string
Q     % Add one to get the next character (the missing one)
c     % Convert to character and display

@ LuisMendo Круто, спасибо!
Suever

2

Excel, 110 + 2 = 112 байт

=CHAR(CODE(LEFT(A1))-1+MATCH(0,IFERROR(FIND(CHAR(ROW(INDIRECT(CODE(LEFT(A1))&":"&CODE(RIGHT(A1))))),A1),0),0))

Должен быть введен как формула массива ( Ctrl+ Shift+ Enter), которая добавляет фигурные скобки { }на каждом конце, добавляя два байта. Ввод в виде строки A1, которая в порядке для каждого OP .

Это далеко не самый короткий ответ (Excel редко бывает), но мне нравится смотреть, можно ли это сделать.



2

CJam , 6 байт (полная программа) / 7 байт (блок кода)

q),^W=

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

Это полная программа CJam, которая считывает входную строку из стандартного ввода и печатает пропущенную букву в стандартный вывод. CJam на самом деле не имеет «методов», что и требует задача, но, вероятно, самым близким будет блок исполняемого кода, например так:

{),^W=}

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

Этот блок кода, при оценке, принимает входные данные в виде строки (то есть массива символов) в стеке и возвращает недостающий символ также в стеке.


Объяснение: В полной программе qчитает входную строку и помещает ее в стек. )затем выскакивает последний символ входной строки, и оператор диапазона ,превращает его в массив, содержащий все символы с кодовыми точками под ним (включая все буквы перед ним в алфавите). Таким образом, например, если ввод был cdfgh, то после ),стека будут содержаться строки cdfg(т.е. ввод с последней удаленной буквой) и...abcdefg , где ...обозначает набор символов с кодами ASCII нижеa (т.е. все символы ниже последнего удаленного ввода письмо).

Затем оператор симметричной разности множеств ^объединяет эти строки в одну строку, которая содержит именно те символы, которые появляются в одной из строк, но не в обеих. Он сохраняет порядок, в котором символы появляются в строках, так что для примера ввода cdfgрезультат после ),^будет ...abe, где ...снова обозначает группу символов с кодами ASCII ниже a. Наконец, W=просто извлекаем последний символ этой строки, который является именно отсутствующим символом, eкоторый мы хотели найти (и отбрасывает остальные). Когда программа заканчивается, интерпретатор CJam неявно распечатывает содержимое стека.


Бонус: GolfScript , 6 байт (полная программа)

),^-1>

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

Оказывается, почти тот же код работает и в GolfScript. Мы сохраняем один байт в полной версии программы из-за неявного ввода GolfScript, но теряем один байт, потому что, в отличие от CJamW , в GolfScript нет удобной однобуквенной переменной, инициализированной -1.

Кроме того, CJam имеет отдельные целочисленные и символьные типы (а строки - это просто массивы, содержащие символы), тогда как GolfScript имеет только один целочисленный тип (и имеет специальный строковый тип, который ведет себя несколько иначе, чем обычные массивы). Результатом всего этого является то, что, если мы хотим, чтобы интерпретатор GolfScript распечатывал фактическую пропущенную букву вместо ее кодового номера ASCII, нам нужно возвращать односимвольную строку вместо только самого символа. К счастью, внесение этого изменения просто требует замены оператора индексации на оператор =усечения массива / строки слева >.

Конечно, благодаря неявному вводу-выводу GolfScript, приведенный выше код также можно использовать как фрагмент, который читает строку из стека и возвращает односимвольную строку, содержащую пропущенную букву. Или, скорее, любой фрагмент, который принимает одну строку в стеке в качестве аргумента и возвращает свой вывод в виде строки для печати в стеке, также является полной программой на языке GolfScript.


6
Фрагменты кода не разрешены по умолчанию ; только функции и полные программы есть. Так что вам, вероятно, нужно это q(программа) или {...}(блок). +1 для подхода, хотя
Луис Мендо

Это очень умно!
Esolanging Fruit

2

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

→S-(ḣ→

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

Эта функция принимает строку (список символов) в качестве входных данных и возвращает символ в качестве выходных данных.

объяснение

→S-(ḣ→
    ḣ→    Get the list of all characters from the null byte to the last character of the input
 S-       Subtract the input from this list
→         Get the last element of the result

2

Python 2 - 76 байт

Проигрывает с существующим решением Python 2, но это немного другой подход, так что я все равно решил опубликовать его:

lambda c:[chr(x)for x in range(ord(c[0]),ord(c[0]+26)if chr(x)not in c][0]

2

8-е , 99 байтов

обоснование

Если расстояние между буквами больше двух, значит, пропущена буква. Буквенное расстояние получается путем вычисления разницы между кодом ASCII каждой буквы.

Код

: f ' nip s:each repeat over n:- 2 n:= if n:1+ "" swap s:+ . reset 1 then depth n:1- while! reset ;

Неуправляемая версия

: f \ s -- c 
  ' nip s:each    \ convert each letter into its ASCII code and put them on stack
  repeat
    over
    n:- 2 n:=     \ check if there is a missing letter 
    if            
      n:1+        \ compute the ASCII code of missing letter
      "" swap s:+ \ convert ASCII code into printable character
      .           \ print out the missing letter
      reset 1     \ set condition to exit from while!
    then
    depth n:1-    \ verify if there are letters to check
  while!          
  reset           \ clean stack
;

Использование и примеры

ok> "abcdf" f
e
ok> "OQRS" f
P
ok> "xz" f
y
ok> "abcdefghijklmnopqrstuwxyz" f
v
ok> "ab" f

ok> "def" f

ok>

2

JavaScript (ES6), 64 байта

Принимает ввод в виде строки.

s=>(g=p=>(c=String.fromCharCode(n++))<s[p]?p?c:g(p):g(p+1))(n=0)

Как?

  • Инициализация: мы начинаем с n = 0 и p = 0 и вызываем рекурсивную функцию g () .

    g = p =>                                   // given p
      (c = String.fromCharCode(n++)) < s[p] ?  // if the next char. c is not equal to s[p]:
        p ?                                    //   if p is not equal to zero:
          c                                    //     step #3
        :                                      //   else:
          g(p)                                 //     step #1
      :                                        // else:
        g(p + 1)                               //   step #2
  • Шаг # 1: Мы увеличиваем n до тех пор, пока не c = String.fromCharCode(n)будет равен первому символу входной строки s [0] .

  • Шаг № 2: Теперь, когда мы синхронизированы, мы одновременно увеличиваем n и p до тех пор, пока c = String.fromCharCode(n)больше не будем равны s [p] .

  • Шаг № 3: Мы возвращаем c : ожидаемый символ, который не был найден.

Контрольные примеры


1

J, 20 байт

{&a.>:I.1 0 1&E.a.e.
  • a.e. логическая маска для ввода букв в кодировке ascii
  • 1 0 1&E. новая логическая маска, указывающая, является ли последовательность 101 начинается с этого индекса, т. е. найти любое место, где начинается последовательность «пропуска»
  • I. индекс этого совпадения, то есть символ перед пропущенным
  • >: увеличение на 1, т. е. индекс пропущенного символа в ascii charset
  • {&a. выберите этот индекс из набора символов ascii, т.е. верните пропущенный символ

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


Это выглядит как фрагмент для меня.
Адам

@ Adám Он написан в молчаливом стиле (без точки), который, как я считаю, считается «функциональным», а не фрагментом. Насколько я могу судить, это не более отрывок, чем ваше решение APL (но я не знаю, dyalog, поэтому возьмите то, что я говорю, с долей соли).
zgrep

@ Adám да, в том смысле, что она не может быть присвоена переменной, но предполагает ввод с правой стороны. это не законно? я где-то спросил об этом, и мне сказали, что все в порядке
Иона

Мое понимание APL / J / K заключается в том, что код должен быть в состоянии находиться в имени, будь то присваивание или как тело явный глагол / функция (однако, у явной формы также должен быть явный ввод). Фрагмент кода - это код, который принимает значения в переменных и / или нуждается в вставке в строку, но не может стоять самостоятельно.
Адам

@zgrep Нет, этот код является явным (не молчаливым), но отсутствует ссылка на его аргумент в крайнем правом углу. Моя функция APL - это полная неявная функция, которую можно назначить или заключить в скобки.
Адам

1

ES6, 125 байт:

(a=>((s,f)=>(r=(i,b)=>a[i]?r(i+1,b||(s[f](i)-s[f](i-1)-1&&String.fromCharCode(s[f](i-1)+1))):b)(1,0))(a.join(""),"charCodeAt"))

http://jsbin.com/vasoqidawe/edit?console

Возвращаемая функция должна вызываться с массивом

(["a","c"])

можно сохранить еще 9 байтов, удалив .join ("") и передав строку:

("ac")

ES6, 108 байт:

(a=>((s,f,o)=>(a.find((_,i)=>(o?++o:o=s[f](i))!==s[f](i)),String.fromCharCode(o)))(a.join(""),'charCodeAt'),0))

http://jsbin.com/tudiribiye/edit?console


1
связать ??? в коде гольф?
edc65

@ edc65 что с ним не так? (извините, если это n00b, но это мой первый гольф :))
Jonas Wilms

@ edc65 но вы, вероятно, правы, удалив его, сохранив 4 байта ...
Джонас

a.join("")может бытьa.join``
user2428118


1

Python 2 , 69 байт

lambda a:chr((ord(a[0])+ord(a[-1]))*-~len(a)/2-sum(ord(x)for x in a))

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

Некоторые объяснения Поскольку мы знаем первый и последний элементы списка, мы можем легко вычислить сумму кодов всех символов в list + the missed char(используя суммарные формулы арифметической прогрессии ). Разница между этой суммой и суммой кодов всех символов в выражениях listдает код пропущенной буквы.


1

05AB1E , 9 7 байт

ǤÝsKçθ

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


Я собираюсь судить по тому, 2что мы используем тот же алгоритм, хотя я едва знаю 05AB1E :)
Leaky Nun

@LeakyNun Ну, я тоже подумал об алгоритме ...
Эрик Аутгольфер

Я просто изменил свой алгоритм, хотя.
Дрянная Монахиня

@LeakyNun Это было бы больше в 05AB1E в любом случае.
Эрик Outgolfer

Я просто подумал о другом алгоритме, который содержит 2 , может быть ваш ...
Leaky Nun

1

APL (Dyalog) , 17 байт

(⊃⎕AV/⍨∨\∧~)⎕AV∘∊

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

⎕AV∘∊ Boolean: каждый символ в элементе A tomic V ector (набор символов) аргумента?

() Применить следующую молчаливую функцию:

 первый элемент

⎕AVTomic V Эктор (набор символов)

/⍨ который

∨\ следует за начальным (член аргумента)

 но

~ нет (участник аргумента)

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