Seleziona la parola attorno all'indice indicato in una determinata stringa


20

In Windows, quando si esegue un doppio clic in un testo, verrà selezionata la parola intorno al cursore nel testo.

(Questa funzione ha proprietà più complicate, ma non sarà necessario implementarle per questa sfida.)

Ad esempio, lascia che |sia il cursore in abc de|f ghi.

Quindi, quando si fa doppio clic, defverrà selezionata la sottostringa .

Input Output

Ti verranno dati due input: una stringa e un numero intero.

Il tuo compito è di restituire la sottostringa di parole della stringa attorno all'indice specificato dall'intero.

Il cursore può essere subito prima o subito dopo il carattere nella stringa nell'indice specificato.

Se lo usi prima , specifica nella tua risposta.

Specifiche (specifiche)

L'indice è garantito all'interno di una parola, quindi nessun caso limite come abc |def ghio abc def| ghi.

La stringa conterrà solo caratteri ASCII stampabili (da U + 0020 a U + 007E).

La parola "parola" è definita dalla regex (?<!\w)\w+(?!\w), dove \wè definita da [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], o "caratteri alfanumerici in ASCII incluso il carattere di sottolineatura".

L'indice può essere 1 indicizzato o 0 indicizzato.

Se usi 0 indicizzato, specifica nella tua risposta.

Casi test

I testcase sono 1 indicizzati e il cursore si trova subito dopo l'indice specificato.

La posizione del cursore è solo a scopo dimostrativo, che non dovrà essere emesso.

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
La stringa può contenere newline?
orlp,

@orlp La sfida è stata modificata per limitare l'input all'ASCII stampabile in modo che l'input non conterrà nuove righe.
FryAmTheEggman,

Le tue prove non contengono altri delimitatori diversi dagli spazi. Che ne dici di una parola come we're?
orlp,

2
Cosa dovrebbe "ab...cd", 3tornare?
Tito

5
@Titus "L'indice è garantito all'interno di una parola"
Martin Ender,

Risposte:


10

V , 10, 9 7 byte

À|diwVp

Provalo online!

Questa risposta utilizza l'indicizzazione basata su 1.

Questo potrebbe essere più breve se facciamo esattamente ciò che dice il titolo: " Seleziona la parola attorno all'indice dato in una stringa". Potremmo fare

À|viw

Che seleziona letteralmente la parola, ma sfortunatamente non cambia affatto l'output. Quindi abbiamo bisogno di un po 'di soluzione per farlo funzionare tagliandolo in un registro, eliminando il resto del testo, quindi incollando nuovamente il registro.

Spiegazione:

À|          " 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 byte

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);}

Si aspetta che l'input su stdin sia l'indice basato su 0 seguito da uno spazio o una nuova riga, seguito dalla stringa. La lunghezza massima di una parola è di 99 caratteri. Per esempio:

2 abc def

È davvero bello vedere C e Perl legati in una sfida basata su stringhe. :D
DJMcMayhem

La stringa di input può contenere più di 100 caratteri?
Leaky Nun,

@LeakyNun Sì, ma una parola non può contenere più di 100 caratteri.
orlp,

Hai voglia di inserire questo requisito nella tua risposta?
Leaky Nun,

@DrGreenEggsandIronMan Peccato che ho dovuto correggere la mia risposta perché era delimitata su spazi bianchi :(
orlp

4

C (gcc), 94 byte

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

Zero-indicizzato, definisce una funzione che prende l'indice, quindi la stringa.


Penso che isalnum(*++p)|*p==95sia un comportamento indefinito.
owacoder,

@owacoder Lo è, ma ciò che conta è che gcc sputa un eseguibile che funziona. *++p^95?isalnum(*p):1è più lungo di un byte, ma funziona su ogni compilatore.
orlp,

Presumo che lo spazio iniziale sia un refuso? Inoltre, ecco un link IDEone pigro.
FryAmTheEggman,

isalnum(*++p)||*p==95funziona anche, per un byte aggiunto.
owacoder,

@FryAmTheEggman Sì, è stato risolto ora.
orlp,

3

Retina, 22

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

Provalo online! o verifica tutti i casi di test . Il programma normale prende la posizione del cursore in unario seguito da una nuova riga e quindi dalla stringa. La suite di test ha un codice aggiuntivo da eseguire in modalità per linea e utilizza a\ un delimitatore e utilizza il decimale per comodità.

Utilizza i gruppi di bilanciamento per trovare la posizione del cursore, quindi torna indietro di un limite di parole. Elimina il testo fino alla parola, quindi dopo la parola.


2

C, 115 byte

La funzione f()richiede la stringa e l'indice (1 indicizzato) come parametri e stampa il risultato su stdout. Il cursore dovrebbe essere dopo il carattere specificato.

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 byte

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

Basta tagliare la stringa nel punto del cursore (che si trova prima del carattere 0 indicizzato, che funziona come dopo il carattere 1 indicizzato), quindi estrae e concatena i frammenti di parole adiacenti. Restituisce anche un risultato sensato quando il cursore si trova all'inizio, alla fine o in nessun punto vicino a una parola.


Hai bisogno del * nell'ultima regex?
Charlie Wynn,

@CharlieWynn Sì, altrimenti la seconda testcase sarebbe solo tornata de.
Neil,

Spiacenti, sono stato sfortunato con i test che ho eseguito
Charlie Wynn, il

2

Java 8, 86 78 byte

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

Non rigato con casi di test:

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));
    }
}

Divide la stringa per caratteri non alfanumerici, quindi continua a sottrarre la lunghezza di ciascuna sottostringa, più 1, dalla posizione specificata, fino a quando diventa negativa. Poiché qualsiasi ripetizione non alfanumerica viene rappresentata come stringa vuota, la logica di sottrazione è notevolmente più semplice.

Questo codice non è ampiamente testato, quindi mi piacerebbe vedere se qualcuno può romperlo. Inoltre, considerando che si tratta del codice Java, in che modo questa non è la risposta più lunga qui? : P


So che sono passati quasi tre anni, ma (s,p)->può essere s->p->usando un'espressione lambda al curry (cioè java.util.function.Function<String, java.util.function.Function<String, String>> f). Inoltre, ora Stringpotrebbe essere varpassato a Java 10, anche se ovviamente non era disponibile al momento. Indipendentemente da ciò, bella risposta. Vedo che l'ho già aggiornato da qualche parte in passato. :)
Kevin Cruijssen,

2

Pyth, 16 byte

+e=:.<+QbE"\W"3h

       Q            first input (string)
      + b           plus newline
    .<   E          rotate left by second input (number)
   :      "\W"3     split on regex \W, non-word characters
  =                 assign to Q
 e                  last element
+              hQ   plus first element

Provalo online



2

Pyke, 19 byte

#Q;cjmli<i+s)lttjR@

Provalo qui!

Utilizza Q;come no-op per assicurarsi che il primo input sia posizionato correttamente

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

Si verifica un errore 504 quando si fa clic sul collegamento.
Leaky Nun,

@LeakyNun Sì, l'ho ucciso per sbaglio mentre scrivevo ed è per questo che avevo il link localhost, tornerà
Blue


1
Sembra che il tuo programma stia producendo N dove è selezionata l'ennesima parola, ma abbiamo bisogno della parola completa
Value Ink

2

Python 2, 70 66 byte

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

Divide la stringa per separatori non di parole, una volta sulla stringa originale fino all'indice del cursore, quindi sulla stringa che inizia dall'indice del cursore. Restituisce l'ultimo elemento della divisione sinistra più il primo elemento della divisione destra. Grazie a Leaky Nun per aver salvato 4 byte!


1

Clojure, 92 byte

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

Innanzitutto, divide la stringa di input in posizione k in due stringhe. Quindi per queste stringhe trovare le occorrenze di "\w+"e restituirle come elenco. Quindi concatenare l'ultimo elemento del primo elenco e il primo elemento del secondo elenco.

Guardalo online: https://ideone.com/Dk2FIs


1

JavaScript (ES6), 52 byte

(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>


Perché (\\W+|^)no(\\W|^)
l4m2

1

Lua, 71 67 byte

Woohoo, Lua non è la soluzione più lunga! Ancora un byte dietro a Python, ma non so come giocare a golf. Gli indici sono basati su 1.

Grazie a @LeakyNun che mi ricorda l'esistenza di string.match, salvato 4 byte

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

Vecchio 71

Nota: le spiegazioni sono ancora basate su questo, perché si applica anche a quello nuovo, ma contiene alcune informazioni aggiuntive su gmatch

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

Spiegazione

Innanzitutto, scompattiamo gli argomenti ge hperché sono più brevi diarg[x]

g,h=...

Quindi, costruiamo il nostro output, che è la concatanazione della parte prima del cursore e dopo di essa.

La prima parte della stringa è

g:sub(1,h)

Vogliamo trovare la parola alla fine di questa, quindi usiamo la funzione string.gmatch

:gmatch"[%a_]*$"

Questa corrispondenza del modello moltiplica 0..nil set di caratteri di alfabeto + carattere di sottolineatura alla fine della stringa. gmatchrestituisce un iteratore sul suo elenco di corrispondenze sotto forma di una funzione (usando il principio di chiusura), quindi lo eseguiamo una volta per ottenere la prima parte della nostra parola

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

Otteniamo la seconda parte della nostra parola allo stesso modo

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

L'unica differenza è che non dobbiamo specificare che vogliamo abbinare all'inizio della stringa (usando [^%a_]*), poiché sarà la corrispondenza restituita dall'iteratore quando viene chiamata la prima volta.


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

@LeakyNun ha completamente dimenticato l'esistenza di match\ o / salva molti byte, grazie
Katenkyo,

-1 per "indici"
Leaky Nun,


Non mi interessa, ancora -1 per "indici".
Leaky Nun,

1

Javascript (utilizzando una libreria esterna) (168 byte)

(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]

Link a lib: https://github.com/mvegh1/Enumerable/blob/master/linq.js

Spiegazione del codice: la libreria accetta una stringa, che viene analizzata in un array di caratteri. Viene mappato su un oggetto che memorizza l'indice e il carattere. La sequenza è suddivisa in sottosequenze ad ogni occorrenza di "". Le sottosequenze vengono filtrate controllando se l'indice del cursore è contenuto tra l'indice minimo e massimo della sottosequenza. Quindi prendiamo la prima sottosequenza. Quindi torniamo a solo un array di caratteri. Quindi concateniamo tutti i caratteri con "" come delimitatore. Quindi convalidiamo contro la parola regex. Quindi prendiamo la prima partita.

enter image description here


La parola "parola" è definita dalla regex (?<!\w)\w+(?!\w), dove \wè definita da [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], o "caratteri alfanumerici in ASCII incluso il carattere di sottolineatura".
Leaky Nun,

Quando eseguo quel regex contro ab! Cd su regex101.com ottengo questo: nessun gruppo di corrispondenza è stato estratto. Questo significa che il tuo modello corrisponde ma non c'erano (catturare (gruppi)) che corrispondessero a qualsiasi cosa nella stringa del soggetto. Forse sto commettendo un errore da qualche parte ...
applejacks01

Perché dovrei catturare qualcosa?
Leaky Nun,

So che questo non è il posto dove imparare, ma sto dicendo che quando eseguo quella regex contro un ab! Cd non ottengo nulla. Quindi perché 'ab' sarebbe l'output corretto?
applejacks01


1

Perl 6 , 34 byte

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

Provalo online!

Blocco codice anonimo che accetta input al curry, come f(n)(string) .

Spiegazione:

->\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

Rubino , 30 byte

->s,n{s[/.{#{n}}\w+/][/\w+$/]}

Provalo online!

Un approccio diverso, solo 1 byte più corto e 3 anni dopo. Perchè no?


1

APL (NARS), 58 caratteri, 116 byte

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

⍵ {⍵≤1: ⍵⋄m∊⍨⍵⊃⍺: ⍺∇⍵-1⋄⍵ + 1} ⍺ trova dove iniziare la stringa ... Come usare e testare:

  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 byte

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

Il cursore è 1-indicizzato e dopo il carattere (come nei casi di test).

Provalo online! Oppure verifica tutti i casi di test .

'\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 byte

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

Una specie di soluzione sciocca, ma un approccio diverso rispetto ad altri.

Accetta l'input $acome indice basato su 0 della stringa $n. Quindi, troviamo i confini della nostra parola. Sebbene non abbiamo raggiunto la fine della stringa e / o stiamo ancora abbinando i caratteri-parola, noi ++$a. Quindi, a causa della recinzione, abbiamo impostato $i=$a--. Successivamente, strisciamo all'indietro, diminuendo $afino a quando non è uno 0o non colpiamo un carattere non di parole. Quindi suddividiamo la stringa di input in base a queste due demarcazioni (con alcuni incrementi / decrementi per tenere conto di OBOE) e -joininsieme per produrre il risultato.

Esempi

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 byte

function f($s,$p){foreach(preg_split('#\W+#',$s,-1,4)as$m)if($m[1]+strlen($m[0])>=$p)return$m[0];}
  • divide la stringa in caratteri non di parole, ricordando la loro posizione ( 4==PREG_SPLIT_OFFSET_CAPTURE ), scorre le parole fino a raggiungere la posizione.
  • Le stringhe PHP sono indicizzate 0, cursore prima del carattere, ma possono essere prima o dopo la parola

0

Python 3, 112 140 byte

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-indicizzati.

Cerca all'indietro il primo carattere alfanumerico dall'indice, quindi passa all'ultimo carattere alfanumerico dopo l'indice. C'è probabilmente un modo più intelligente per farlo.

Provalo


È _stato aggiunto @LeakyNun , non sono sicuro del motivo per cui avrei ricevuto un errore f('abc',1).
atlanteologo

0

JavaScript (ES 6), 43 42 byte

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

JavaScript (ES 3), 65 byte

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

0

05AB1E , 14 byte

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

Porto di @AndersKaseorg 'il Pyth risposta .

1 indicizzato come i casi di test di sfida.

Provalo online o verifica tutti i casi di test .

Spiegazione:

ð«              # 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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.