Знайдіть пропущений лист


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'


Чи можу я замість цього взяти рядок?
Leaky Nun

@LeakyNun Strings - це масиви символів, так що так.
Amorris

1
Чи може висновок бути масивом, що містить відсутній символ (наприклад: для вводу ['a','b','c','d','f','g'], виводу ['e'], якщо це робить код коротшим?
Містер Xcoder

1
@ Mr.Xcoder Рядок - це лише масив символів, так що так
Amorris

2
Правило четверте - це просто підмножина правила восьмого і його можна видалити (принаймні, якщо ви введете слово "включно" в кінці правила восьмого).
NH.

Відповіді:



11

C # (.NET Core) , 48 47 46 байт, введення як масив char

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) -байтове рішення, ввічливість Едьки:

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[]). Не завдяки мені btw, завдяки коментарю @Nevay до моєї відповіді на Java 8 .
Kevin Cruijssen

1
@KevinCruijssen знайшов спосіб зберегти ще два байти, приймаючи дані як масив char.
Чарлі

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)
1717

Я б сказав, що foo(char*a){return*a+1==a[1]?foo(a+1):++*a;}це досить добре; Тільки на 1 char коротше природногоfoo(char*a){while(*a+1==a[1])a++;return++*a;}
1717

@ постійне невизначене поведінку вважається прийнятним в PPCG
Ган

5

Пітон 3 , 74 62 58 44 40 байт

-12 байтів завдяки Еріку Переможнику. -18 байт завдяки Leaky Nun. -4 байти завдяки musicman523.

Приймає введення як тестування.

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

Спробуйте в Інтернеті!

Ще одне класне рішення:

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

1
.difference({*s})->-{*s}
Ерік Аутгольфер




1
Ваше рішення - це те, про що я хотів, але набагато більш елегантним
Pureferret

4

Математика, 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 Prolog, 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 Dennis

@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, що є нормальним для кожної ОП .

Це далеко не найкоротша відповідь (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, але втрачаємо один байт, оскільки, на відміну від CJam W, 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
  • {&a. виберіть цей індекс із діаграми ascii, тобто поверніть пропущений символ

Спробуйте в Інтернеті!


Мені це схоже на фрагмент.
Adám

@ Adám Це написано в негласному (без точкового) стилі, який, на мою думку, вважається "функціональним" на відміну від фрагмента. Як найкраще я можу сказати, це не більше фрагмент, ніж ваше рішення APL (але я не знаю діалога, тому візьміть те, що я скажу, із зерном солі).
zgrep

@ Adám так, це в тому сенсі, що він не може бути призначений змінній, але передбачає введення з правого боку. це не законно? я десь запитав про це і мені сказали, що це добре
Jonah

Я розумію, що APL / J / K полягає в тому, що код повинен бути в змозі містити ім'я, чи то за призначенням, чи як в тілі явного дієслова / функції (однак, явна форма повинна також мати явний вклад). Snippet - це код, який приймає значення змінних та / або потребує вставки в рядок, але не може стояти самостійно.
Адам

@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 whats wrong with it ? ( sorry if this is n00b, but thats my first golf :))
Jonas Wilms

@edc65 but youre probably right, removing it saved 4 bytes...
Jonas Wilms

a.join("") could be a.join``
user2428118


1

Python 2, 69 bytes

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

Try it online!

Some explanations As we know the first and the last elements of the list, we can easily compute the sum of the codes of all the chars in the list + the missed char (using summary formulas of arithmetic progression). The difference between this sum and the sum of the codes of all the chars in the list gives the code of the missed letter.



1

APL (Dyalog), 17 bytes

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

Try it online!

⎕AV∘∊ Boolean: each character in the Atomic Vector (character set) member of the argument?

() apply the following tacit function:

 the first element of

⎕AV the Atomic Vector (the character set)

/⍨ which

∨\ follows the initial (member of the argument)

 but

~ is not (a member of the argument)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.