Sélectionnez le mot autour de l'index donné dans une chaîne donnée


20

Sous Windows, lorsque vous effectuez un double-clic dans un texte, le mot autour de votre curseur dans le texte sera sélectionné.

(Cette fonctionnalité a des propriétés plus compliquées, mais il ne sera pas nécessaire de les implémenter pour ce défi.)

Par exemple, laissez |votre curseur entrer abc de|f ghi.

Ensuite, lorsque vous double-cliquez, la sous-chaîne defsera sélectionnée.

Entrée sortie

Vous recevrez deux entrées: une chaîne et un entier.

Votre tâche consiste à renvoyer la sous-chaîne de mots de la chaîne autour de l'index spécifié par l'entier.

Votre curseur peut être placé juste avant ou juste après le caractère de la chaîne à l'index spécifié.

Si vous utilisez juste avant , veuillez préciser dans votre réponse.

Spécifications (spécifications)

L'index est garanti à l'intérieur d'un mot, donc pas de cas de bord comme abc |def ghiou abc def| ghi.

La chaîne ne contiendra que des caractères ASCII imprimables (de U + 0020 à U + 007E).

Le mot "mot" est défini par l'expression régulière (?<!\w)\w+(?!\w), où \west défini par [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], ou "caractères alphanumériques en ASCII, y compris le soulignement".

L'index peut être indexé 1 ou indexé 0.

Si vous utilisez l'index 0, veuillez le spécifier dans votre réponse.

Cas de test

Les cas de test sont indexés 1 et le curseur se trouve juste après l'index spécifié.

La position du curseur est uniquement à des fins de démonstration, qui ne devra pas être sortie.

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 chaîne peut-elle contenir des sauts de ligne?
orlp

@orlp Le défi a été modifié pour restreindre l'entrée en ASCII imprimable afin que l'entrée ne contienne pas de nouvelles lignes.
FryAmTheEggman

Vos testcases ne contiennent pas d'autres délimiteurs que des espaces. Et un mot comme we're?
orlp

2
Qu'est-ce qui devrait "ab...cd", 3revenir?
Titus

5
@Titus "L'index est garanti dans un mot"
Martin Ender

Réponses:


10

V , 10, 9 7 octets

À|diwVp

Essayez-le en ligne!

Cette réponse utilise l'indexation basée sur 1.

Cela pourrait être plus court si nous faisons exactement ce que dit le titre: " Sélectionnez le mot autour de l'index donné dans une chaîne". Nous pourrions faire

À|viw

Ce qui sélectionne littéralement le mot, mais ne change malheureusement pas du tout la sortie. Nous avons donc besoin d'une petite solution pour le faire fonctionner en le découpant dans un registre, en supprimant le reste du texte, puis en le collant à nouveau.

Explication:

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

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

S'attend à ce que l'entrée sur stdin soit l'index de base 0 suivi d'un espace ou d'un saut de ligne, suivi de la chaîne. La longueur maximale d'un mot est de 99 caractères. Par exemple:

2 abc def

C'est vraiment cool de voir C et Perl liés sur un défi basé sur des chaînes. :D
DJMcMayhem

La chaîne d'entrée peut-elle contenir plus de 100 caractères?
Leaky Nun

@LeakyNun Oui, mais un mot ne peut pas dépasser 100 caractères.
orlp

Envie de mettre cette exigence dans votre réponse?
Leaky Nun

@DrGreenEggsandIronMan Dommage que j'ai dû corriger ma réponse car elle était délimitée sur les espaces blancs :(
orlp

4

C (gcc), 94 octets

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

Zéro indexé, définit une fonction prenant l'index, puis la chaîne.


Je pense que isalnum(*++p)|*p==95c'est un comportement indéfini.
owacoder

@owacoder C'est vrai, mais ce qui importe, c'est que gcc crache un exécutable qui fonctionne. *++p^95?isalnum(*p):1est un octet de plus, mais fonctionne sur tous les compilateurs.
orlp

Je suppose que l'espace de tête est une faute de frappe? En outre, voici un lien IDEone paresseux.
FryAmTheEggman

isalnum(*++p)||*p==95fonctionne également, pour un octet supplémentaire.
owacoder

@FryAmTheEggman Oui, c'est résolu maintenant.
orlp

3

Rétine, 22

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

Essayez-le en ligne! ou vérifiez tous les cas de test . Le programme régulier prend la position du curseur en unaire suivi d'un retour à la ligne puis de la chaîne. La suite de tests a du code supplémentaire à exécuter en mode par ligne, et utilise un \comme délimiteur, et il utilise décimal, pour plus de commodité.

Utilise des groupes d'équilibrage pour trouver la position du curseur, puis revient en arrière jusqu'à une limite de mot. Supprime le texte jusqu'au mot, puis après le mot.


2

C, 115 octets

La fonction f()requiert la chaîne et l'index (indexé 1) comme paramètres et imprime le résultat sur stdout. Le curseur doit se trouver après le caractère spécifié.

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 octets

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

Tranche simplement la chaîne au point du curseur (qui est avant le caractère indexé 0, ce qui revient au même qu'après le caractère indexé 1), puis extrait et concatène les fragments de mots adjacents. Renvoie même un résultat sensible lorsque le curseur est au début, à la fin ou loin d'un mot.


Avez-vous besoin du * dans le dernier regex?
Charlie Wynn

@CharlieWynn Oui, sinon le deuxième testcase ne reviendrait que de.
Neil

whoops, malchanceux avec les tests que j'ai effectués
Charlie Wynn

2

Java 8, 86 78 octets

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

Non golfé avec des cas de 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));
    }
}

Divise la chaîne par des caractères non alphanumériques, puis continue de soustraire la longueur de chaque sous-chaîne, plus 1, de la position spécifiée, jusqu'à ce qu'elle devienne négative. Étant donné que tout caractère non alphanumérique répétitif est représenté sous forme de chaîne vide, la logique de soustraction est nettement plus facile.

Ce code n'est pas testé intensivement, donc j'aimerais voir si quelqu'un peut le casser. De plus, étant donné qu'il s'agit de code Java, comment n'est-ce pas la réponse la plus longue ici? : P


Je sais que cela fait presque trois ans, mais cela (s,p)->peut être s->p->en utilisant une expression lambda currying (ie java.util.function.Function<String, java.util.function.Function<String, String>> f). De plus, cela Stringpourrait être le varcas si vous passiez à Java 10, bien que cela ne soit pas disponible à l'époque bien sûr. Quoi qu'il en soit, belle réponse. Je vois que je l'ai déjà mis à jour quelque part dans le passé. :)
Kevin Cruijssen

2

Pyth, 16 octets

+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

Essayez-le en ligne



2

Pyke, 19 octets

#Q;cjmli<i+s)lttjR@

Essayez-le ici!

Utilise Q;comme no-op pour s'assurer que la première entrée est placée correctement

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

Je rencontre une erreur 504 lorsque je clique sur votre lien.
Leaky Nun

@LeakyNun Oui, je l'ai tué par accident lors de l'écriture, c'est pourquoi j'ai eu le lien localhost, il reviendra
Blue


1
Votre programme semble produire N où le Nième mot est celui sélectionné, mais nous avons besoin du mot complet
Value Ink

2

Python 2, 70 66 octets

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

Fractionne la chaîne par des séparateurs autres que des mots, une fois sur la chaîne d'origine jusqu'à l'index du curseur, puis sur la chaîne commençant à l'index du curseur. Renvoie le dernier élément de la division gauche plus le premier élément de la division droite. Merci à Leaky Nun d'avoir économisé 4 octets!


1

Clojure, 92 octets

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

Tout d'abord, divise la chaîne d'entrée à la position ken deux chaînes. Ensuite, pour ces chaînes, recherchez les occurrences de "\w+"et renvoyez-les sous forme de liste. Ensuite, concaténez le dernier élément de la première liste et le premier élément de la deuxième liste.

Voir en ligne: https://ideone.com/Dk2FIs


1

JavaScript (ES6), 52 octets

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


Pourquoi (\\W+|^)pas(\\W|^)
l4m2

1

Lua, 71 67 octets

Woohoo, Lua n'est pas la solution la plus longue! Encore un octet derrière python, mais je ne sais pas comment jouer au golf. Les index sont basés sur 1.

Merci à @LeakyNun me rappelant l'existence de string.match, sauvé 4 octets

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

Vieux 71

Remarque: les explications sont toujours basées sur celle-ci, car elle s'applique également à la nouvelle, mais contient des informations supplémentaires sur gmatch

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

Explication

Tout d'abord, nous décompressons les arguments dans get hparce qu'ils sont plus courts quearg[x]

g,h=...

Ensuite, nous construisons notre sortie, qui est la concatanation de la pièce avant et après le curseur.

La première partie de la chaîne est

g:sub(1,h)

Nous voulons trouver le mot à la fin de celui-ci, nous utilisons donc la fonction string.gmatch

:gmatch"[%a_]*$"

Cette correspondance de motif 0..nmultiplie le jeu de caractères alphabet + trait de soulignement à la fin de la chaîne. gmatchrenvoie un itérateur sur sa liste de correspondance sous la forme d'une fonction (en utilisant le principe de fermeture), nous l'exécutons donc une fois pour obtenir la première partie de notre mot

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

Nous obtenons la deuxième partie de notre parole de la même manière

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

La seule différence étant que nous n'avons pas à spécifier que nous voulons faire correspondre au début de la chaîne (en utilisant [^%a_]*), car ce sera la correspondance renvoyée par l'itérateur lors de son premier appel.


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

@LeakyNun a totalement oublié l'existence de match\ o / enregistre beaucoup d'octets, merci
Katenkyo

-1 pour "index"
Leaky Nun


Je m'en fiche, toujours -1 pour les "index".
Leaky Nun

1

Javascript (à l'aide d'une bibliothèque externe) (168 octets)

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

Lien vers la bibliothèque: https://github.com/mvegh1/Enumerable/blob/master/linq.js

Explication du code: la bibliothèque accepte une chaîne, qui est analysée dans un tableau de caractères. Il est mappé à un objet stockant l'index et le caractère. La séquence est divisée en sous-séquences à chaque occurrence de "". Les sous-séquences sont filtrées en vérifiant si l'index du curseur est contenu dans l'index min et max de la sous-séquence. Ensuite, nous prenons la première sous-séquence. Ensuite, nous nous transformons en un simple tableau de caractères. Ensuite, nous concaténons tous les caractères avec "" comme délimiteur. Ensuite, nous validons le mot regex. Ensuite, nous prenons le premier match.

entrez la description de l'image ici


Le mot "mot" est défini par l'expression régulière (?<!\w)\w+(?!\w), où \west défini par [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], ou "caractères alphanumériques en ASCII, y compris le soulignement".
Leaky Nun

Lorsque je lance cette expression rationnelle contre ab! Cd sur regex101.com, j'obtiens ceci: Aucun groupe de correspondance n'a été extrait. Cela signifie que votre modèle correspond mais qu'il n'y en avait pas (capture (groupes)) qui correspondait à quoi que ce soit dans la chaîne du sujet. Peut-être que je fais une erreur quelque part ...
applejacks01

Pourquoi aurais-je besoin de capturer quelque chose?
Leaky Nun

Je sais que ce n'est pas l'endroit pour apprendre, mais je dis que lorsque je lance cette expression rationnelle contre ab! Cd, je ne reçois rien. Alors pourquoi «ab» serait-il la sortie correcte?
applejacks01


1

Perl 6 , 34 octets

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

Essayez-le en ligne!

Bloc de code anonyme qui prend les entrées au curry, comme f(n)(string).

Explication:

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

Rubis , 30 octets

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

Essayez-le en ligne!

Une approche différente, seulement 1 octet plus court et 3 ans plus tard. Pourquoi pas?


1

APL (NARS), 58 caractères, 116 octets

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

⍵ {⍵≤1: ⍵⋄m∊⍨⍵⊃⍺: ⍺∇⍵-1⋄⍵ + 1} ⍺ trouver où commencer la chaîne ... Comment utiliser et tester:

  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 octets

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

Le curseur est indexé 1 et après le caractère (comme dans les cas de test).

Essayez-le en ligne! Ou vérifiez tous les cas de 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 octets

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

Une sorte de solution loufoque, mais une approche différente des autres.

Prend l'entrée $acomme l'index basé sur 0 de la chaîne $n. Ensuite, nous trouvons les limites de notre parole. Bien que nous n'ayons pas atteint la fin de la chaîne et / ou que nous correspondions toujours à des mots, nous ++$a. Puis, à cause de la clôture, nous nous sommes mis $i=$a--. Ensuite, nous rampons vers l'arrière, en décrémentant $ajusqu'à ce que ce soit 0ou que nous frappions un caractère autre qu'un mot. Nous coupons ensuite la chaîne d'entrée en fonction de ces deux démarcations (avec quelques incréments / diminutions pour tenir compte de l'OBOE), et -joinensemble pour produire le résultat.

Exemples

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 octets

function f($s,$p){foreach(preg_split('#\W+#',$s,-1,4)as$m)if($m[1]+strlen($m[0])>=$p)return$m[0];}
  • divise la chaîne en caractères non-mots, en se souvenant de leur position ( 4== PREG_SPLIT_OFFSET_CAPTURE), parcourt les mots jusqu'à ce que la position soit atteinte.
  • Les chaînes PHP sont indexées 0, le curseur avant le caractère, mais peut être avant ou après le mot

0

Python 3, 112 140 octets

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 indexé.

Recherche en arrière le premier caractère alphanumérique de l'index, puis avance jusqu'au dernier caractère alphanumérique après l'index. Il existe probablement une façon plus intelligente de procéder.

Essayez-le


@LeakyNun a _été ajouté, je ne sais pas pourquoi j'obtiendrais une erreur f('abc',1).
atlasologue

0

JavaScript (ES 6), 43 42 octets

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

JavaScript (ES 3), 65 octets

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

0

05AB1E , 14 octets

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

Port de @AndersKaseorg « s réponse Pyth .

1-indexé comme les cas de test de défi.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

ð«              # 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)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.