Виберіть слово навколо заданого індексу в заданому рядку


20

У Windows при виконанні подвійного клацання в тексті буде вибрано слово навколо курсору в тексті.

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

Наприклад, дозвольте |бути курсором уabc de|f ghi .

Потім, коли ви двічі клацніть, defбуде вибрано підрядку .

Введення-виведення

Вам буде надано два входи: рядок і ціле число.

Ваше завдання полягає в тому, щоб повернути слово-підрядку рядка навколо індексу, визначеного цілим числом.

Ваш курсор може бути прямо перед або прямо після символу в рядку за вказаним індексом.

Якщо ви користувалися прямо раніше , вкажіть, будь ласка, у своїй відповіді.

Технічні характеристики (характеристики)

Індекс гарантовано знаходиться всередині слова, тому жодних крайових випадків, як abc |def ghiабо abc def| ghi.

Рядок містить лише символи для друку ASCII (від U + 0020 до U + 007E).

Слово "слово" визначається регулярним виразом (?<!\w)\w+(?!\w), де \wвизначено [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], або "буквено-цифровими символами в ASCII, включаючи підкреслення".

Індекс може бути 1-індексованим або 0-індексованим.

Якщо ви використовуєте 0-індексацію, вкажіть це у своїй відповіді.

Тестові шафи

Тестові шкали є 1-індексованими, а курсор знаходиться відразу після вказаного індексу.

Позиція курсору призначена лише для демонстрації, яку не потрібно буде виводити.

string    index     output    cursor position
abc def   2         abc       ab|c def
abc def   5         def       abc d|ef
abc abc   2         abc       ab|c abc
ab cd ef  4         cd        ab c|d ef
ab   cd   6         cd        ab   c|d
ab!cd     1         ab        a|b!cd

2
Чи може рядок містити нові рядки?
orlp

@orlp Виклик було відредаговано для обмеження введення для друку ASCII, щоб вхід не містив нових рядків.
FryAmTheEggman

Ваші тестові шкали не містять ніяких інших роздільників, ніж пробіли. Що про таке слово, як we're?
orlp

2
Що слід "ab...cd", 3повернути?
Тит

5
@Titus "Індекс гарантовано міститиме слово"
Мартін Ендер

Відповіді:


10

V , 10, 9 7 байт

À|diwVp

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

У цій відповіді використовується індексація на основі 1.

Це може бути коротше, якщо ми виконаємо саме те, що говорить заголовок: " Виберіть слово навколо вказаного індексу в рядку". Ми могли б зробити

À|viw

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

Пояснення:

À|          " Jump the position of argument 1
  diw       " (d)elete (i)nside this (w)ord.
     V      " Select this line
      p     " And replace it with the word we just deleted

5

C, 104 байти

p[99];i,d;main(l){for(scanf("%d",&i);scanf("%[^a-zA-Z0-9_]%[a-zA-Z0-9_]%n",&d,&p,&l),i>l;i-=l);puts(p);}

Очікує, що вхід на stdin буде індексом на основі 0, а потім пробілом або новим рядком, а потім рядком. Максимальна довжина слова - 99 символів. Наприклад:

2 abc def

Дуже приємно бачити, як C та perl прив'язані до виклику на основі струни. :D
DJMcMayhem

Чи може рядок введення містити більше 100 символів?
Leaky Nun

@LeakyNun Так, але одне слово не може бути довше 100 символів.
orlp

Ви відчуваєте, як ставити цю вимогу всередині своєї відповіді?
Leaky Nun

@DrGreenEggsandIronMan Шкода, що мені довелося виправити свою відповідь, оскільки вона була обмежена на пробіли :(
orlp

4

C (gcc), 94 байт

f(n,p)char*p;{for(p+=n-1;isalnum(*p)|*p==95&&n--;--p);for(;isalnum(*++p)|*p==95;putchar(*p));}

Нульова індексація, визначає функцію, що приймає індекс, а потім рядок.


Я думаю, що isalnum(*++p)|*p==95це невизначена поведінка.
owacoder

@owacoder Так, але важливо, що gcc виплетає виконуваний файл, який працює. *++p^95?isalnum(*p):1є на один байт довше, але працює на кожному компіляторі.
orlp

Я припускаю, що провідний простір - це друкарська помилка? Також ось лінивий посилання IDEone.
FryAmTheEggman

isalnum(*++p)||*p==95також працює, для доданого байта.
owacoder

@FryAmTheEggman Так, це виправлено зараз.
orlp

3

Сітківка, 22

(1) + ¶ (? <-1>.) * \ B | \ W. +

Спробуйте в Інтернеті! або перевірити всі тестові випадки . Звичайна програма займає позицію курсора в одинаковому, а потім новий рядок і потім рядок. Тестовий набір має додатковий код для запуску в режимі рядка та використовує\ як роздільник, а для зручності він використовує десятковий.

Використовує врівноважуючі групи для пошуку позиції курсору, а потім відновлює до межі слова. Видаляє текст до слова, а потім після слова.


2

C, 115 байт

Функція f()вимагає рядок та індекс (1-індексований) як параметри та друкує результат для stdout. Курсор повинен бути після вказаного символу.

f(char*p,int n){char*s=p+n;for(;s>=p&&isalnum(*s)+(*s==95);--s);for(p=s+1;*p&&isalnum(*p)+(*p==95);putchar(*p++));}

2

JavaScript (ES6), 57 байт

f=(s,n)=>s.slice(0,n).match(/\w*$/)+s.slice(n).match(/\w*/)

Просто нарізає рядок у точці курсору (що знаходиться перед символом 0-індексом, який працює так само, як після 1-індексованого символу), після чого витягує та з'єднує суміжні фрагменти слова. Навіть повертає розумний результат, коли курсор знаходиться в початку, в кінці або ніде поблизу слова.


Вам потрібен * * в останньому регулярному виразі?
Charlie Wynn

@CharlieWynn Так, інакше другий тест лише повернеться de.
Ніл

ну, не пощастило з тестами, які я пробіг
Чарлі Війн

2

Java 8, 86 78 байт

(s,p)->{for(String t:s.split("\\W"))if((p-=t.length()+1)<0)return t;return"";}

Недоліковані з тестовими кейсами:

class Indexer {
    public static String f(String s, int p) {
        for(String t : s.split("\\W"))
            if((p -= t.length()+1) < 0)
                return t;
        return "";
    }

    public static void main(String[] args) {
        System.out.println(f("abc def",2));
        System.out.println(f("abc def",5));
        System.out.println(f("abc abc",2));
        System.out.println(f("ab cd ef",4));
        System.out.println(f("ab   cd",6));
        System.out.println(f("ab!cd",1));
    }
}

Розбиває рядок на не алфавітно-цифрові символи, потім продовжує віднімати довжину кожної підрядки плюс 1 від заданої позиції, поки вона не стане від’ємною. Оскільки будь-які повторювані не буквено-цифрові знаки представляються порожніми рядками, логіка віднімання значно простіша.

Цей код недостатньо перевірений, тому я хотів би дізнатися, чи може хтось це порушити. Крім того, враховуючи, що це код Java, як це не найдовша відповідь тут? : P


Я знаю, що минуло майже три роки, але (s,p)->можна s->p->, використовуючи висловлювання лямбда-виразу (тобто java.util.function.Function<String, java.util.function.Function<String, String>> f). Окрім того, Stringможна було varб перейти на Java 10, хоча на той час це було недоступно. Незалежно, приємна відповідь. Я бачу, що я його вже оновлював десь у минулому. :)
Кевін Круїссен



2

Пайк, 19 байт

#Q;cjmli<i+s)lttjR@

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

Використовується Q;як неоперативний, щоб переконатися, що перший ввід розміщено правильно

#          )   -  first where
   c           -       input.split()
    ml         -      map(len, ^)
      i<       -     ^[:i]
        i+     -    ^+[i]
          s    -   sum(^)
            lt - len(^)-2

У мене помилка 504, коли я натискаю ваше посилання.
Лина монашка

@LeakyNun Так, я вбив його випадково, поки писав, через що у мене було посилання localhost, воно повернеться
Blue


1
Здається, ваша програма виводить N, де вибране N-е слово, але нам потрібне повне слово
Value Ink

2

Python 2, 70 66 байт

import re
f=lambda x,y,r=re.split:r('\W',x[:y])[-1]+r('\W',x[y:])[0]

Розбиває рядок на несловові роздільники, один раз на початкову рядок до індексу курсору, потім на рядок, що починається з покажчика курсору. Повертає останній елемент лівого розколу плюс перший елемент правого розколу. Дякуємо Leaky Nun за збереження 4 байтів!


1

Clojure, 92 байти

(fn[x k](let[[u i](map #(re-seq #"\w+"(apply str %))(split-at k x))](str(last u)(nth i 0))))

По-перше, розбиває вхідний рядок у положенні kна два рядки. Тоді для цих рядків знайдіть входження "\w+"та поверніть їх як список. Потім з'єднайте останній елемент першого списку та перший елемент другого списку.

Дивіться це в Інтернеті: https://ideone.com/Dk2FI


1

JavaScript (ES6), 52 байти

(s,n)=>RegExp(`^.{0,${n}}(\\W+|^)(\\w+)`).exec(s)[2]

const F = (s,n) => RegExp(`^.{0,${n}}(\\W+|^)(\\w+)`).exec(s)[2]

class Test extends React.Component {
    constructor(props) {
        super(props);
        const input = props.input || '';
        const index = props.index || 0;
        this.state = {
            input,
            index,
            valid: /\w/.test(input),
        };
    }
    onInput = () => {
        const input = this.refs.input.value;
        const index = Math.min(+this.refs.index.value, input.length);
        this.setState({
            input,
            index,
            valid: /\w/.test(input),
        });
    }
    render() {
        const {input, index, valid} = this.state;
        return (
            <tr>
                <td>{ this.props.children }</td>
                <td>
                    <input ref="input" type="text" onInput={this.onInput} value={input} />
                    <input ref="index" type="number" onInput={this.onInput} min="1" max={input.length} value={index} />
                </td> 
                {valid && [
                    <td>{F(input, index)}</td>,
                    <td><pre>{input.slice(0, index)}|{input.slice(index)}</pre></td>,
                ]}
            </tr>
        );
    }
}

class TestList extends React.Component {
    constructor(props) {
        super(props);
        this.tid = 0;
        this.state = {
            tests: (props.tests || []).map(test => Object.assign({
                key: this.tid++
            }, test)),
        };
    }
    addTest = () => {
        this.setState({
            tests: [...this.state.tests, { key: this.tid++ }],
        });
    }
    removeTest = key => {
        this.setState({
            tests: this.state.tests.filter(test => test.key !== key),
        });
    }
    
    render() {
        return (
            <div>
                <table>
                    <thead>
                        <th/>
                        <th>Test</th>
                        <th>Output</th>
                        <th>Diagram</th>
                    </thead>
                    <tbody>
                        {
                            this.state.tests.map(test => (
                                <Test key={test.key} input={test.input} index={test.index}>
                                    <button onClick={() => this.removeTest(test.key)} style={{
                                        verticalAlign: 'middle',
                                    }}>-</button>
                                </Test>
                            ))
                        }
                    </tbody>
                    <tfoot>
                        <td/>
                        <td>
                            <button onClick={this.addTest} style={{
                                width: '100%',
                            }}>Add test case</button>
                        </td>
                    </tfoot>
                </table>
            </div>
        );
    }
}

ReactDOM.render(<TestList tests={[
    { input: 'abc def', index: 2 },
    { input: 'abc def', index: 5 },
    { input: 'abc abc', index: 2 },
    { input: 'ab cd ef', index: 4 },
    { input: 'ab   cd', index: 6 },
    { input: 'ab!cd', index: 1 },
]} />, document.body);
input[type="number"] {
  width: 3em;
}
table {
  border-spacing: 0.5em 0;
  border-collapse: separate;
  margin: 0 -0.5em ;
}
td, input {
    font-family: monospace;
}
th {
  text-align: left;
}
tbody {
  padding: 1em 0;
}
pre {
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>


Чому б і (\\W+|^)ні(\\W|^)
l4m2

1

Луа, 71 67 байт

Woohoo, Lua - це не найдовше рішення! Ще один байт за пітоном, але не знаю, як це робити вниз. Індекси базуються на 1.

Завдяки @LeakyNun нагадуючи мені про існування string.match, збережено 4 байти

g,h=...print(g:sub(1,h):match"[%a_]*$"..g:sub(h+1):match("[%a_]+"))

Старий 71 рік

Примітка: пояснення все ще базуються на цьому, оскільки воно також стосується нового, але містить додаткову інформацію про gmatch

g,h=...print(g:sub(1,h):gmatch"[%a_]*$"()..g:sub(h+1):gmatch"[%a_]*"())

Пояснення

По-перше, ми розпаковуємо аргументи gі hтому, що вони коротшіarg[x]

g,h=...

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

Перша частина рядка - це

g:sub(1,h)

Ми хочемо знайти слово в кінці цього, тому використовуємо функцію string.gmatch

:gmatch"[%a_]*$"

Цей візерунок збігається 0..nз набором символів алфавіту + підкреслення в кінці рядка. gmatchповертає ітератор до списку відповідності у вигляді функції (за принципом закриття), тому ми виконуємо його один раз, щоб отримати першу частину нашого слова

g:sub(1,h):gmatch"[%a_]*$"()

Другу частину нашого слова ми отримуємо тим самим чином

g:sub(h+1):gmatch"[%a_]*"())

Єдина відмінність полягає в тому, що ми не повинні вказувати, чи хочемо ми відповідати на початку рядка (використовуючи [^%a_]*), оскільки це буде відповідність, повернута ітератором при першому виклику.


g:sub(h+1):match"^[%a_]*"?
Leaky Nun

@LeakyNun повністю забув про існування match\ o / економить багато байтів, спасибі
Katenkyo

-1 для "індексів"
Leaky Nun


Мені все одно, досі -1 для "індексів".
Leaky Nun

1

Javascript (за допомогою зовнішньої бібліотеки) (168 байт)

(n,w)=> _.From(w).Select((x,i)=>({i:i,x:x})).Split((i,v)=>v.x==" ").Where(a=>a.Min(i=>i.i)<=n-1&&a.Max(i=>i.i)>=n-2).First().Select(i=>i.x).Write("").match(/^\w*^\w*/)[0]

Посилання на lib: https://github.com/mvegh1/Enumerable/blob/master/linq.js

Пояснення коду: Бібліотека приймає рядок, який розбирається в масив char. Він відображається на об’єкт, що зберігає індекс та таблицю. Послідовність розбивається на підрядники при кожному виникненні "". Підстави фільтрують, перевіряючи, чи міститься індекс курсору в межах мінімального та максимального індексу підрядності. Тоді ми беремо першу підпорядкованість. Потім ми перетворюємось назад просто на масив char. Тоді ми з'єднуємо всі символи як "" роздільник. Тоді ми підтверджуємо слово regex. Тоді ми беремо перший матч.

enter image description here


Слово "слово" визначається регулярним виразом (?<!\w)\w+(?!\w), де \wвизначено [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], або "буквено-цифровими символами в ASCII, включаючи підкреслення".
Leaky Nun

Коли я запускаю цей регекс проти ab! Cd на regex101.com, я отримую це: жодна група збігів не вилучалася. Це означає, що ваш шаблон відповідає, але в ньому не було (захоплення (груп)), які б відповідали чому-небудь у темі. Можливо, я десь помиляюся ...
applejacks01

Навіщо мені потрібно щось захопити?
Лина монашка

Я знаю, що це не місце вчитися, але я кажу, що коли я запускаю цей регекс проти ab! Cd, я нічого не отримую. То чому б "ab" був правильним результатом?
applejacks01


1

Perl 6 , 34 байти

->\b{&{first *.to>b,m:g/<<\w+>>/}}

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

Анонімний кодовий блок, який приймає вхід з викривленням, як f(n)(string) .

Пояснення:

->\b{                            }   # Anonymous code block that takes a number
     &{                         }    # And returns another code block that
       first       ,m:g/<<\w+>>/     # Finds the first word in the input
             *.to>b                  # Where the start is after the number


1

APL (NARS), 58 символів, 116 байт

{m←⎕A,⎕a,⎕D,'_'⋄↑v⊂⍨m∊⍨v←⍵↓⍨¯1+⍵{⍵≤1:⍵⋄m∊⍨⍵⊃⍺:⍺∇⍵-1⋄⍵+1}⍺}

⍵ {⍵≤1: ⍵⋄m∊⍨⍵⊃⍺: ⍺∇⍵-1⋄⍵ + 1} ⍺ знайдіть з чого почати рядок ... Як користуватися та тестувати:

  f←{m←⎕A,⎕a,⎕D,'_'⋄↑v⊂⍨m∊⍨v←⍵↓⍨¯1+⍵{⍵≤1:⍵⋄m∊⍨⍵⊃⍺:⍺∇⍵-1⋄⍵+1}⍺}
  2 f 'abc def'
abc
  5 f 'abc def'
def
  2 f 'abc abc'
abc
  4 f 'ab cd ef'
cd
  1 f 'ab!cd'
ab
  6 f 'ab   cd'
cd 

0

MATL , 16 15 байт

'\w+'5B#XXi>)1)

Курсор 1-індексований і після символу (як у тестових випадках).

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

'\w+'    % Push string to be used as regex pattern
5B#XX    % Take input string implicitly. Apply regex. Push matches and ending indices
i>       % Take input number. Compare with obtained ending indices. Gives true for
         % ending indices that exceed the input number
)        % Use as logical index to select the corresponding matches
1)       % Select the first match. Implicitly display

0

PowerShell v3 +, 103 101 байт

param($a,$n)for(;$n[++$a]-match'\w'){}$i=$a--;for(;$n[--$a]-match'\w'-and$a-ge0){}-join$n[++$a..--$i]

Вигляд гуфічного рішення, але інший підхід, ніж інші.

Приймає введення $aяк 0 на основі індексу рядка $n. Тоді ми знаходимо межі нашого слова. Поки ми не досягли кінця рядка та / або ми все ще узгоджуємо слова-символи, ми ++$a. Потім, через огорожу, ми встановлюємо $i=$a--. Далі ми повзаємо назад, зменшуючи $aдо тих пір, поки це не стане або 0не потрапимо до символу без слова. Потім ми розрізаємо вхідний рядок на основі цих двох розмежувань (з деяким збільшенням / зменшенням для обліку OBOE), і-join це разом для отримання результату.

Приклади

PS C:\Tools\Scripts\golfing> .\select-the-word-around-the-index.ps1 2 'This!test'
This

PS C:\Tools\Scripts\golfing> .\select-the-word-around-the-index.ps1 5 'This!test'
test

select-the-word-around-the-index.ps1
Leaky Nun

0

PHP, 98 байт

function f($s,$p){foreach(preg_split('#\W+#',$s,-1,4)as$m)if($m[1]+strlen($m[0])>=$p)return$m[0];}
  • розбиває рядок на символи, що не містять слів, запам'ятовуючи їх положення (4 == PREG_SPLIT_OFFSET_CAPTURE), прокручує слова, поки не буде досягнуто позиції.
  • Рядки PHP індексуються 0, курсор перед символом, але може бути перед словом або після нього

0

Python 3, 112 140 байт

from string import*
p='_'+printable[:62]
def f(s,h,r=''):
 while s[h]in p and h>-1:h-=1
 while h+1<len(s)and s[h]in p:h+=1;r+=s[h]
 return r

0-індексований.

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

Спробуй це


@LeakyNun _було додано, я не впевнений, чому я отримав помилку, f('abc',1)хоча.
атласолог

0

JavaScript (ES 6), 43 42 байт

s=>n=>s.replace(/\w*/g,(x,y)=>y<n?s=x:0)&&s

JavaScript (ES 3), 65 байт

function(s,n){s.replace(/\w*/g,function(x,y){y<n?s=x:0});alert(s)}

0

05AB1E , 14 байт

ð«._DžjмS¡Á2£J

Порт відповіді Pyth @AndersKaseorg .

1-індексовано, як тестові випадки.

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

Пояснення:

ð«              # Append a space to the (implicit) input-String
  ._            # Rotate this string the (implicit) input-integer amount of times
                #  towards the left
     D          # Duplicate this string
      žjм       # Remove [a-zA-Z0-9_] from the string
         S¡     # Split the rotated string by each of the remaining characters
           Á    # Rotate the resulting list once towards the right
            2£J # And only leave the first two items, joined together
                # (which is output implicitly)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.