Зменшити рядок до фрагмента алфавіту


25

Враховуючи не порожній рядок, що складається лише з нижнього та верхнього регістру буквених символів та пробілів ( [a-zA-Z ]), зменшіть його до фрагмента алфавіту, починаючи з першого символу.

Щоб зменшити рядок, почніть з першого алфавітного символу, а потім видаліть кожен символ після нього, який не є наступною літерою алфавіту. Продовжуйте робити це, поки не досягнете кінця рядка.

Наприклад codegolf:

Почніть з c, видаліть, oоскільки це не наступна літера алфавіту.
Продовжуйте , dяк це є наступною буквою алфавіту, і зберегти , eяк це наступна буква теж.
Видаліть g, oта lі збережіть f.

Тоді буде ваш остаточний фрагмент cdef

Правила

  • Капіталізацію слід підтримувати, щоб CodEgolFце призвело доCdEF
  • Пробіл не є буквою алфавіту, і тому його завжди слід видаляти, навіть якщо це початок рядка
  • Зважаючи на характер скорочення, перший алфавітний символ введення завжди буде першим символом виводу.
  • zZ- остання літера алфавіту. Букви після неї не бувають, алфавіт не циркулює.

Випробування

codegolf -> cdef
CodEgolf -> CdEf
 codeolfg -> cdefg
ProgrammingPuzzles -> P
Stack Exchange -> St
The quick red fox jumped over the lazy brown dog -> Tuvw
Zebra -> Z
Abcdegfhijkl -> Abcdef

Оцінка балів

Це , тому виграє найменше байтів на кожній мові !


З другого останнього тестового випадку я бачу, що якщо ми дійдемо, zми просто зупинимось, правда?
Містер Xcoder

@ Mr.Xcoder Правильно, останній пункт див. У "Правилах"
Skidsdev

2
Будь ласка, додайте тестовий випадок із пробілом на початку. Як:<space>codegolf
Містер Xcoder

Чи можу я повернути масив вихідних літер?
TheLethalCoder

1
@ Mr.Xcoder так можна
Skidsdev

Відповіді:


12

JavaScript (ES6), 66 79 68 67 байт

f=([c,...s],p)=>c?(p?~parseInt(c+p,36)%37:c<'!')?f(s,p):c+f(s,c):''

Як?

Тестування послідовних листів

Оскільки перетворення двох символів у їх ASCII-коди було б досить тривалою операцією в JS, ми використовуємо наступну формулу:

~parseInt(b + a, 36) % 37

При умови , що обидва і б в , наведене вище вираз не дорівнює тоді і тільки тоді , коли і Ь є послідовними літери (тобто послідовних цифр в базі 36), незалежно від того , регістр символів.[a-zA-Z ]0

Наприклад:

~parseInt("Y" + "x", 36) = ~(36 * parseInt("Y", 36) + parseInt("x", 36))
                         = ~(36 * 34 + 33)
                         = -(36 * 34 + 33 + 1)
                         = -(37 * 34)

Відформатовано та прокоментовано

f = ([c,                              // c = current character
         ...s],                       // s = array of remaining characters
                p) =>                 // p = previous matching letter
  c ? (                               // if there's still at least 1 character to process:
      p ?                             //   if p was already defined:
        ~parseInt(c + p, 36) % 37     //     test if p and c are NON-consecutive letters
      :                               //   else:
        c < '!'                       //     test if c is a space character
    ) ?                               //   if the above test passes:
      f(s, p)                         //     ignore c and keep the current value of p
    :                                 //   else:
      c + f(s, c)                     //     append c to the final result and update p to c
  :                                   // else:
    ''                                //   stop recursion

Тестові справи


7

Python 2 , 69 байт

lambda s:reduce(lambda x,y:x+y*((ord(y)-ord(x[~0]))%32==1),s.strip())

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

Просте скорочення рядка. Ми просто об'єднуємо наступний символ, якщо і тільки якщо (ord(y)-ord(x[~0]))%32==1. Дуже некрасива перевірка - я впевнений, що її можна покращити, але я не впевнений, як!


Розумне рішення! Шкода, що це лише Python 2: P
Містер Xcoder

Ви можете зробити його сумісним із Python 3 за допомогою from functools import*.
повністюлюдський

1
@ThomasWard абсолютно нелюдсько просто розповідав іншим, як зробити його Python 3 сумісним. Btw, import functools as fі f.набагато довше, ніж from functools import*точно, навіть використовується один раз. Дивіться цю тему для отримання додаткової інформації.
Містер Xcoder

7

Пітон 3 , 75 85 84 91 81 77 75 байт

Я думаю, що це так коротко, як це може потрапити в Python 3 . Його можна скоротити на кілька байтів у Python 2, як показано у поданні Сизіфа .

  • EDIT: +10 для виправлення помилки
  • EDIT: -1 шляхом виправлення ще однієї помилки
  • Редагувати: +7 для виправлення ще однієї помилки
  • EDIT: -10 байт за допомогою @Ruud
  • Редагувати: -4 байти, оскільки OP дозволив нам виводити літери, розділені новим рядком
  • РЕДАКТУВАТИ : -2 байти завдяки @Ruud , повернутися до початкового підрахунку байтів!
s=input().strip();k=0
for i in s:
 if(ord(i)-ord(s[0]))%32==k:k+=1;print(i)

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


У мене є ідеї для вдосконалення, незабаром гольф на мобільних.
Містер Xcoder

2
81 байт . Великі і малі літери зручно збігаються, коли їх модулюють 32
Arfie

@Ruud Це саме те, про що я говорив у своєму коментарі, редагуванні.
Містер Xcoder


8
Я чекаю, коли пояснювач пояснить їх причини.
Містер Xcoder


4

Брахілог , 15 байт

;ṢxS⊇.ḷ~sẠ∧Sh~h

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

Це було б 10 байт: ⊇.ḷ~sẠ&h~hякби не досить нецікаве обмеження "рядки можуть починатися з пробілів".

Пояснення

;ṢxS               S is the Input with all spaces removed
   S⊇.             The Output is an ordered subset of the Input
     .ḷ            The Output lowercased…
        ~sẠ          …is a substring of "abcdefghijklmnopqrstuvwxyz"
           ∧
            Sh     The first char of S…
              ~h   …is the first char of the Output

Оскільки це досить декларативно, це теж дуже повільно.


Ну, принаймні це б'є желе! І, з позитивного боку, я не думаю, що ти справді зможеш перемогти це ...
Ерік Вигнавець

3

MATL , 18 16 15 байт

Дякуємо Mr.Xcoder за вказівку на помилку, яку тепер виправлено

Xz1&)"t@hkd1=?@

Букви на виході розділені новими рядками.

Спробуйте в Інтернеті! Або перевірити всі тестові випадки (код нижнього колонтитулу відображає всі вихідні літери в одному рядку для наочності).

Пояснення

Xz       % Implicitly input a string. Remove spaces
1&)      % Push first character and then the remaining substring
"        % For each
  t      %   Duplicate previous character
  @      %   Push current character
  h      %   Concatenate both characters
  k      %   Convert to lowercase
  d      %   Consecutive difference. Gives a number
  1=     %   Is it 1?
  ?      %   If so
    @    %     Push current char
         %   End (implicit)
         % End (implicit)
         % Display stack (implicit)

Ви забули видалити пробіли, коли вони знаходяться на початку рядка: Пробіл не є буквою алфавіту, і тому завжди слід видаляти, навіть якщо це початок рядка .
Містер Xcoder

@ Mr.Xcoder Дякую! Виправлено
Луїс Мендо


2

C # (Моно) , 129 107 93 91 87 байт

s=>{var r=s.Trim()[0]+"";foreach(var c in s)if(r[r.Length-1]%32==~-c%32)r+=c;return r;}

Збережено 2 байти завдяки @Mr. Xcoder.
Збережено 4 байти завдяки @jkelm.

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


Невдача на провідних просторах
Skidsdev

@Mayube Woops не бачив цього, виправлений.
TheLethalCoder

2
91 байт . На мовах подібних С та Python, (c-1)%32це~-c%32
містер Xcoder

1
87 байт Вам не потрібно перепризначати обрізану рядок через перевірки циклу for
jkelm

2

PHP, 64 + 1 байт

while($c=$argn[$i++])$c<A||$n&&($c&_)!=$n||(print$c)&$n=++$c&__;

Запустіть як трубу -nRабо спробуйте в Інтернеті .


Крім звичайних хитрощів: Коли $cдосягаєZ , ++$cпризводить AA,
і &__тримається , що довжина недоторканим; тому $nбільше не буде відповідати $c.



2

Haskell, 106 105 97 байт

import Data.Char
import Data.List
z=ord.toUpper
a%b|z a+1==z b=b|0<3=a
nub.scanl1(%).filter(>' ')

Я намагався використовувати fromEnumарифметику + char замість імпортуData.Char , але це в кінцевому підсумку було довше ...

Збережено 8 байт завдяки H.PWiz!

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



Або 100 байт зData.List
H.PWiz

@ H.PWiz Чудово! Спасибі!
Крістіан Лупаску

2

Pyth, 21 20 18 байт

ef&qhThQhxGrT0tyr6

Спробуйте тут.

Шмат ефективніша 20-байтна версія:

.U+b?t-CrZ1Creb1kZr6

Спробуйте тут.

-1 дякую містеру Xcoder (опосередковано).


Еквівалент: .U+b?tlrreb1rZ1kZrz6(я думаю). Цей трюк мені допоміг.
Містер Xcoder

@ Mr.Xcoder Якби це було еквівалентом, я міг би зберегти байт з, .U+b?tlrreb1rZ1kZr6але, на жаль, r <str> 6означає A.strip(), не видаляючи пробіли, що не ведуть чи затримують пробіли.
Erik the Outgolfer

О так, я не бачив, як ваше рішення покладається на те, що всі пробіли будуть видалені (мій ні)
Містер Xcoder

@ Mr.Xcoder Umm, вам слід видалити всі пробіли.
Erik the Outgolfer

Ні, я не повинен, оскільки простір має значення ASCII 32, хоча всі букви мають > 64, і, таким чином, не впливають на функціональність. Я думаю, це стосується і вашої відповіді.
Містер Xcoder

1

Perl 6 , 51 байт

{S:i:g/\s|(\w){}<([<!before "{chr $0.ord+1}">.]+//}

Перевірте це

Розширено:

{  # bare block lambda with implicit parameter $_

  S                          # substitute implicitly on $_, not in-place
  :ignorecase
  :global
  /

    |  \s                    # match any space

    |  (\w)                  # match a word character
       {}                    # make sure $/ is updated (which $0 uses)

       <(                    # ignore everything before this

       [

           <!before "{       # make sure this won't match after this point
             chr $0.ord + 1  # the next ASCII character
           }">

           .                 # any character

       ]+                    # match it at least once

  //                         # remove what matched
}

Зауважте, що <!before …>це твердження нульової ширини



1

Japt , 18 17 16 байт

Збережено 1 байт завдяки @Shaggy

x
c
Çc %H¥V%H©V°

Перевірте це в Інтернеті!

Думав, що це було б трохи коротше, але ... Таке життя ...

Пояснення

x    First line: set U to the result.
x    Trim all spaces off of the input. Only necessary to remove leading spaces.

c    Second line: set V to the result.
c    Take the charcode of the first character in U.

 Ç   c %H¥ V%H© V°
UoZ{Zc %H==V%H&&V++}   Final line: output the result.
UoZ{               }   Filter to only the chars in Z where
    Zc                   the charcode of Z
       %H                mod 32
         ==V%H           equals V mod 32.
              &&V++      If true, increment V for the next letter.

Коротше, ніж мої 28-байтні травесті! : D Схоже , ви можете замінити rSз x.
Кудлатий

1

C # (.NET Core) , 70 60 + 18 байт

-10 байт завдяки TheLethalCoder

a=>{var c=a.Trim()[0];return a.Where(x=>x%32==c%32&&++c>0);}

Кількість байтів включає також:

using System.Linq;

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

На 1 байт довше (зараз) (не більше), ніж повідомлення TheLethalCoder, щоб розмістити їх заради забави. Інший підхід, з LINQ.

Це використовує дві C-подібні функції у C # - символьна charзмінна неявно поводиться так само, як ціле число int, і булева оператор AND &&не виконує правильну операцію, якщо ліва повертає a false. Пояснення коду:

a =>                                  // Take string as input
{
    var c = a.Trim()[0];              // Delete leading spaces and take first letter
    return a.Where(                   // Filter out characters from the string, leaving those that:
               x => x % 32 == c % 32  // it's the next character in alphabet case-insensitive (thanks to modulo 32 - credits to previous answers)
               && ++c > 0             // If it is, go to the subsequent character in alphabet (and this always has to return true)
           );
}

Видаліть .ToArray(), повернувшись як IEnumerable<char>збереження байтів.
TheLethalCoder

@TheLethalCoder правильно, я щойно побачив коментар під викликом. Дякую!
Grzegorz Puławski

1

q / kdb +, 47 45 байт

Рішення:

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}

Приклади:

q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"CodEgolf"
"CdEf"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}" codeolfg"
"cdefg"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"ProgrammingPuzzles"
"P"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"The quick red fox jumped over the lazy brown dog"
"Tuvw"

Пояснення:

Використання mod 32хитрості від існуючих рішень разом із функцією конвергенції . Повторіть рядок, якщо різниця між останнім елементом результату (наприклад, починається з T"Швидкої червоної лисиці ...") і поточним символом дорівнює 1 (після того, як mod"d з 32"), ми додаємо це до результат (значить, чому ми беремо last x), а потім відкидаємо все назад у рядок.

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x} / the solution
{                                           } / lambda function
                                      trim x  / trim whitespace (leading/trailing)
                                   7h$        / cast string to ASCII (a -> 97)
     ({                         }/)           / converge
                    y-last x                  / y is the next item in the list, x contains results so far
              1=mod[        ;32]              / is the result mod 32 equal to 1
       (x;x,y)                                / if false, return x, if true return x concatenated with y
 10h$                                         / cast back to characters


0

Сітківка , 76 байт

 

^.
$&$&$&¶
{T`@@L@l`@l@l@`..¶
T`l`L`.¶
(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

Спробуйте в Інтернеті!Посилання включає тестові випадки. Пояснення:

 

Видаліть пробіли.

^.
$&$&$&¶

Помножте вдвічі перший символ і вставте роздільник.

{T`@@L@l`@l@l@`..¶
T`l`L`.¶

Перетворіть другий та третій символи в малі та збільшуйте їх. Перетворіть останній у верхній регістр. Зараз це символи пошуку.

(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

Спробуйте відповідати будь-якому із символів пошуку. Якщо він знайдений, то збірте три рази збіг, який перезапустить цикл для наступного пошуку. В іншому випадку просто видаліть пошукові символи та решту введених даних.


0

8-й , 114 байт

Код

: z dup n:1+ 32 bor >r "" swap s:+ . ; 
: f s:trim 0 s:@ z ( nip dup 32 bor r@ n:= if rdrop z then ) s:each rdrop ;

Пояснення

: z             \ n -- (r: x)
                \ print letter and save on r-stack OR-bitwised ASCII code of following letter
  dup           \ duplicate item on TOS
  n:1+          \ get ASCII code of the following letter
  32 bor        \ bitwise OR of ASCII code and 32 
  >r            \ save result on r-stack
  "" swap s:+ . \ print letter
;

: f        \ s -- 
  s:trim   \ remove trailing whitespace
  0 s:@    \ get 1st letter
  z        \ print 1st letter and save on r-stack OR-bitwised ASCII code of following letter
  ( nip    \ get rid of index
    dup    \ duplicate item on TOS
    32 bor \ bitwise OR of current ASCII code and 32 
    r@     \ get value stored on r-stack
    n:=    \ compare values to see if letter is printable or not
    if 
      rdrop \ clean r-stack
      z     \ print letter and save on r-stack OR-bitwised ASCII code of following letter
    then 
  ) 
  s:each    \ handle each character in string
  rdrop     \ clean r-stack
;

Приклад

ok> " The quick red fox jumped over the lazy brown dog" f
Tuvw



0

Pyth, 15 байт

eo,}r0NG_xQhNty

Тестовий набір

На відміну від усіх інших відповідей, це не злипає результат, він генерує всі підрядки введення, а потім наказує їм поставити потрібний рядок у кінці та виводить його.


Я думаю, ви повинні перевірити, чи перша літера виводу є також і першою літерою вводу. І я думаю, що початкове замовлення має значення.
Ерік Аутгольфер

@EriktheOutgolfer Вибачте, ви говорите, що відповідь неправильна? Я переконуюсь, що послідовність, перший символ якої є найчастіше у введенні серед усіх послідовностей, які є в алфавітному порядку, є відсортованою до кінця. Дивіться тестовий випадок, починаючи з пробілу.
isaacg

Чи можете ви додати пояснення, будь ласка? Можливо, я зрозумів неправильно або щось таке ...
Ерік Позашляховик

0

J, часткове рішення

Я публікую це для зворотного зв'язку та ідей для вдосконалення більше, ніж будь-що інше. Це працює, але не обробляє регістри з великої літери та крайового простору, і вже давно для Дж.

Спершу дієслово-діадєр-помічник, яке повідомляє, чи лівий і правий аргументи буквенно суміжні:

g=.(= <:)&(a.&i.)  NB. could save one char with u:

Далі дієслово, яке видаляє перший елемент, який не є частиною алфавітного рядка, починаючи з першого елемента:

f=.({~<^:3@>:@i.&0@(0,~2&(g/\))) ::]

Зауважте, ми використовуємо Adverse :: щоб повернути весь аргумент без змін, якщо не знайдено елемент без рядка (тобто, якщо весь аргумент є дійсним алфавітним рядком).

Нарешті, рішення дається шляхом застосування fдо конвергенції:

f^:_ 'codegolf'  NB. => 'cdef'

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


І ось розібрана версія f для легшого читання:

           ┌─ ~ ─── {                         
           │                              ┌─ <
           │                       ┌─ ^: ─┴─ 3
           │                 ┌─ @ ─┴─ >:      
       ┌───┤           ┌─ @ ─┴─ i.            
       │   │     ┌─ & ─┴─ 0                   
       │   │     │                            
       │   └─ @ ─┤     ┌─ 0                   
── :: ─┤         │     ├─ ~ ─── ,             
       │         └─────┤                      
       │               │     ┌─ 2             
       │               └─ & ─┴─ \ ─── / ──── g
       └─ ]         

Побічне запитання : чому символи поля не ідеально вирівнюються під час відображення на SO (вони працюють у моїй консолі):

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