指定された文字列で指定されたインデックスの周りの単語を選択します


20

Windowsでは、テキストをダブルクリックすると、テキスト内のカーソルの周りの単語が選択されます。

(この機能にはより複雑なプロパティがありますが、このチャレンジのために実装する必要はありません。)

たとえば|、にカーソルを合わせabc de|f ghiます。

次に、ダブルクリックすると、部分文字列defが選択されます。

入出力

文字列と整数の2つの入力が与えられます。

あなたの仕事は、整数で指定されたインデックスの周りの文字列の単語部分文字列を返すことです。

カーソルは、指定されたインデックスの文字列の文字の直前または直後置くことができます。

直前に使用する場合は、回答に明記してください。

仕様(仕様)

インデックスは単語内にあることが保証されているため、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

V10、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ベースのインデックスの後に1つのスペースまたは改行が続き、その後に文字列が続くことを想定しています。単語の最大長は99文字です。例えば:

2 abc def

Cとperlが文字列ベースのチャレンジに結びついているのを見るのは本当にクールです。:D
DJMcMayhem

入力文字列は100文字を超えることはできますか?
リーキー修道女

@LeakyNunはい、ただし、1つの単語は100文字を超えることはできません。
orlp

その要件を答えの中に入れたいと思いますか?
リーキー修道女

@DrGreenEg​​gsandIronMan残念ながら、空白で区切られていたため、答えを修正する必要がありました。(
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):11バイト長くなりますが、すべてのコンパイラで動作します。
orlp

先頭のスペースはタイプミスだと思いますか?また、ここに怠oneなIDEoneリンクがあります。
-FryAmTheEggman

isalnum(*++p)||*p==95追加された1バイトに対しても機能します。
-owacoder

@FryAmTheEggmanはい、修正されました。
-orlp

3

網膜、22

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

オンラインでお試しください!または、すべてのテストケースを確認します。通常のプログラムは、カーソル位置を単項式にし、その後に改行と文字列を続けます。テストスイートには、行単位モードで実行する追加のコードがあり、\、区切り文字としてa便宜上10進数を使用します。

バランスグループを使用してカーソル位置を見つけ、単語境界までバックトラックします。単語まで、および単語の後のテキストを削除します。


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インデックスの文字の後と同じように動作します)で文字列をスライスし、隣接する単語の断片を抽出して連結します。カーソルが開始位置、終了位置、または単語の近くにない場合でも、適切な結果を返します。


最後の正規表現に*が必要ですか?
チャーリーウィン

@CharlieWynnはい、そうでない場合、2番目のテストケースはのみを返し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


ほぼ3年が経ちましたが、カリー化するラムダ式(つまり)を使用する(s,p)->ことで実現できます。また、可能性がJavaの10に切り替えた場合には、当然の時点で利用可能ではなかったが、今。とにかく、いい答え。過去のどこかで既に更新しているようです。:)s->p->java.util.function.Function<String, java.util.function.Function<String, String>> fStringvar
ケビンクルーッセン



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のリンクを持っていたされている理由書き込みながら、事故によってそれを殺し、それが戻ってくる
ブルー


1
あなたのプログラムは、N番目のワードが選択されるものであるNを出力しているようだが、我々は完全な言葉を必要とする
バリューインクに

2

パイソン2、70の 66バイト

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

文字列を非ワード区切り文字で分割します。一度元の文字列でカーソルインデックスまで、次にカーソルインデックスで始まる文字列で分割します。左分割の最後の要素と右分割の最初の要素を返します。4バイトを節約してくれたLeaky Nunに感謝します!


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を2つの文字列に分割します。次に、これらの文字列の出現を検索"\w+"し、リストとして返します。次に、最初のリストの最後の要素と2番目のリストの最初の要素を連結します。

オンラインで見る:https : //ideone.com/Dk2FIs


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

Lua、71 67バイト

うーん、Luaは最長の解決策ではありません!まだPythonの1バイト後ろにありますが、これをゴルフで打つ方法がわかりません。インデックスは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_]*$"()

同じように私たちの言葉の2番目の部分を取得します

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

唯一の違いは[^%a_]*、イテレータが最初に呼び出されたときにイテレータによって返される一致であるため、文字列の先頭で一致するように指定する必要がないことです(を使用)。


g:sub(h+1):match"^[%a_]*"
リーキー修道女

@LeakyNunの存在を完全に忘れてしまった match、感謝のO /バイトの節約を\
Katenkyo

-1の「インデックス」
リーキー修道女


気にしませんが、「インデックス」は-1です。
リーキー修道女

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配列に変換します。次に、すべての文字を区切り文字として「」で連結します。次に、単語の正規表現に対して検証します。次に、最初のマッチを取ります。

enter image description here


単語「言葉」は正規表現で定義され(?<!\w)\w+(?!\w)\wによって定義される[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]、または「アンダースコアを含むASCIIで英数字」。
リーキー修道女

regex101.comでab!cdに対してその正規表現を実行すると、次のようになります。一致グループが抽出されませんでした。これは、パターンは一致するが、件名文字列のいずれにも一致する(キャプチャ(グループ))がないことを意味します。たぶん私は間違いのどこかを作ってるんだ...
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

MATL16 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または、単語以外の文字にヒットします。次に、これら2つの境界に基づいて入力文字列をスライスします(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
リーキー修道女

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

@AndersKaseorgのPyth回答のポート。

チャレンジテストケースのように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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.