Pilih kata di sekitar indeks yang diberikan dalam string yang diberikan


20

Di Windows, ketika Anda melakukan klik dua kali dalam sebuah teks, kata di sekitar kursor Anda dalam teks akan dipilih.

(Fitur ini memiliki sifat yang lebih rumit, tetapi tidak perlu diterapkan untuk tantangan ini.)

Misalnya, biarkan |kursor Anda masuk abc de|f ghi.

Kemudian, ketika Anda mengklik dua kali, substring defakan dipilih.

Input output

Anda akan diberikan dua input: string dan integer.

Tugas Anda adalah mengembalikan kata-substring dari string di sekitar indeks yang ditentukan oleh integer.

Kursor Anda bisa tepat sebelum atau tepat setelah karakter dalam string di indeks yang ditentukan.

Jika Anda menggunakan tepat sebelumnya , sebutkan jawaban Anda.

Spesifikasi (Spesifikasi)

Indeks dijamin berada di dalam kata, jadi tidak ada tepi kasus seperti abc |def ghiatau abc def| ghi.

String hanya akan berisi karakter ASCII yang dapat dicetak (dari U + 0020 hingga U + 007E).

Kata "kata" didefinisikan oleh regex (?<!\w)\w+(?!\w), di mana \wdidefinisikan oleh [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], atau "karakter alfanumerik di ASCII termasuk garis bawah".

Indeks dapat diindeks 1 atau 0 diindeks.

Jika Anda menggunakan 0-diindeks, harap tentukan dalam jawaban Anda.

Testcases

Testcases diindeks 1, dan kursor tepat setelah indeks ditentukan.

Posisi kursor hanya untuk tujuan demonstrasi, yang tidak akan diminta untuk dikeluarkan.

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
Bisakah string berisi baris baru?
orlp

@ orlp Tantangan telah diedit untuk membatasi input ke ASCII yang dapat dicetak sehingga input tidak akan berisi baris baru.
FryAmTheEggman

Testcases Anda tidak mengandung pembatas selain ruang. Bagaimana dengan kata seperti itu we're?
orlp

2
Apa yang harus "ab...cd", 3dikembalikan?
Titus

5
@Titus "Indeks ini dijamin berada di dalam kata"
Martin Ender

Jawaban:


10

V , 10, 9 7 byte

À|diwVp

Cobalah online!

Jawaban ini menggunakan pengindeksan berbasis 1.

Ini bisa lebih pendek jika kita melakukan persis apa yang dikatakan judul: " Pilih kata di sekitar indeks yang diberikan dalam sebuah string". Kita bisa lakukan

À|viw

Yang benar-benar memilih kata, tetapi sayangnya tidak mengubah output sama sekali. Jadi kita perlu sedikit solusi untuk membuatnya bekerja dengan memotongnya menjadi register, menghapus sisa teks, lalu menempelkan register kembali.

Penjelasan:

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

Mengharapkan input pada stdin menjadi indeks berbasis 0 diikuti oleh satu spasi atau baris baru, diikuti oleh string. Panjang maksimal kata adalah 99 karakter. Misalnya:

2 abc def

Sangat keren melihat C dan perl terikat pada tantangan berbasis string. :D
DJMcMayhem

Bisakah string input memiliki lebih dari 100 karakter?
Leaky Nun

@ LeakyNun Ya, tapi satu kata tidak boleh lebih dari 100 karakter.
orlp

Apakah Anda merasa ingin memasukkan persyaratan itu ke dalam jawaban Anda?
Leaky Nun

@DrGreenEggsandIronMan Sayang sekali saya harus memperbaiki jawaban saya karena dibatasi di whitespace :(
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));}

Diindeks nol, mendefinisikan fungsi mengambil indeks, lalu string.


Saya pikir itu isalnum(*++p)|*p==95adalah perilaku yang tidak terdefinisi.
owacoder

@owacoder Ya, tapi yang penting gcc memuntahkan executable yang berfungsi. *++p^95?isalnum(*p):1lebih panjang satu byte, tetapi bekerja pada setiap kompiler.
orlp

Saya menganggap ruang terdepan adalah kesalahan ketik? Juga, inilah tautan IDEone yang malas.
FryAmTheEggman

isalnum(*++p)||*p==95juga berfungsi, untuk satu byte tambahan.
owacoder

@FryAmTheEggman Ya, sudah diperbaiki sekarang.
orlp

3

Retina, 22

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

Cobalah online! atau verifikasi semua kasus uji . Program reguler mengambil posisi kursor di unary diikuti oleh baris baru dan kemudian string. Test suite memiliki kode tambahan untuk dijalankan dalam mode per baris, dan menggunakan \sebagai pembatas, dan menggunakan desimal, untuk kenyamanan.

Menggunakan kelompok penyeimbang untuk menemukan posisi kursor, lalu mundur ke batas kata. Menghapus teks hingga kata, lalu setelah kata.


2

C, 115 byte

Fungsi f()membutuhkan string dan indeks (1-diindeks) sebagai parameter dan mencetak hasilnya ke stdout. Kursor harus setelah karakter yang ditentukan.

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*/)

Cukup iris string pada titik kursor (yang sebelum karakter 0-diindeks, yang bekerja sama seperti setelah karakter 1-diindeks), lalu ekstrak dan gabungkan fragmen kata yang berdekatan. Bahkan mengembalikan hasil yang masuk akal ketika kursor berada di awal, akhir, atau tempat dekat kata.


Apakah Anda memerlukan * di regex terakhir?
Charlie Wynn

@CharlieWynn Ya, kalau tidak testcase kedua hanya akan kembali de.
Neil

wah, beruntung dengan tes yang saya jalankan
Charlie Wynn

2

Java 8, 86 78 byte

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

Tidak disatukan dengan kasus uji:

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

Pisahkan string dengan karakter non-alfanumerik, lalu terus kurangi panjang setiap substring, ditambah 1, dari posisi yang ditentukan, hingga menjadi negatif. Karena non-alfanumerik berulang diwakili sebagai string kosong, logika pengurangan lebih mudah.

Kode ini tidak diuji secara luas, jadi saya ingin melihat apakah seseorang dapat memecahkan ini. Juga, mengingat ini adalah kode Java, bagaimana ini bukan jawaban terpanjang di sini? : P


Saya tahu ini sudah hampir tiga tahun, tetapi (s,p)->bisa s->p->dengan menggunakan ekspresi lambda yang kari (yaitu java.util.function.Function<String, java.util.function.Function<String, String>> f). Selain itu, Stringbisa jadi varsekarang jika beralih ke Java 10, meskipun itu tidak tersedia pada saat itu tentu saja. Apapun, jawaban yang bagus. Saya melihat saya sudah memperbaruinya di suatu tempat di masa lalu. :)
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

Cobalah online



2

Pyke, 19 byte

#Q;cjmli<i+s)lttjR@

Coba di sini!

Digunakan Q;sebagai no-op untuk memastikan input pertama ditempatkan dengan benar

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

Saya mengalami kesalahan 504 ketika saya mengklik tautan Anda.
Leaky Nun

@ LeakyNun Ya, saya membunuhnya secara tidak sengaja saat menulis itulah sebabnya saya memiliki tautan localhost, itu akan kembali
Biru


1
Program Anda tampaknya menghasilkan N di mana kata N adalah yang dipilih, tetapi kami membutuhkan kata lengkap
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]

Pisahkan string dengan pemisah non-kata, sekali pada string asli hingga indeks kursor, kemudian pada string yang dimulai pada indeks kursor. Mengembalikan elemen terakhir dari perpecahan kiri ditambah elemen pertama dari perpecahan kanan. Terima kasih kepada Leaky Nun karena telah menghemat 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))))

Pertama, pisahkan string input pada posisi kmenjadi dua string. Kemudian untuk string ini menemukan kemunculan"\w+" dan kembalikan sebagai daftar. Kemudian gabungkan elemen terakhir dari daftar pertama dan elemen pertama dari daftar kedua.

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


Mengapa (\\W+|^)tidak(\\W|^)
14m2

1

Lua, 71 67 Bytes

Woohoo, Lua bukan solusi terpanjang! Masih satu byte di belakang python, tetapi tidak tahu cara bermain golf ini. Indeks berbasis 1.

Terima kasih kepada @LeakyNun yang mengingatkan saya akan keberadaannya string.match, menyelamatkan 4 byte

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

71 tahun

Catatan: penjelasannya masih didasarkan pada yang ini, karena juga berlaku untuk yang baru, tetapi berisi beberapa informasi tambahan tentang gmatch

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

Penjelasan

Pertama, kami membongkar argumen ke gdan hkarena mereka lebih pendek dariarg[x]

g,h=...

Kemudian, kami membuat output kami, yang merupakan penutup bagian sebelum kursor dan setelahnya.

Bagian pertama dari string adalah

g:sub(1,h)

Kami ingin menemukan kata di akhir kata ini, jadi kami menggunakan fungsinya string.gmatch

:gmatch"[%a_]*$"

Pola ini cocok dengan 0..nkali rangkaian karakter alfabet + garis bawah pada akhir string. gmatchmengembalikan iterator pada daftar kecocokannya dalam bentuk fungsi (menggunakan prinsip penutupan), jadi kami menjalankannya sekali untuk mendapatkan bagian pertama dari kata kami

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

Kita mendapatkan bagian kedua dari kata kita dengan cara yang sama

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

Satu-satunya perbedaan adalah kita tidak harus menentukan kita ingin mencocokkan pada awal string (menggunakan [^%a_]*), karena itu akan menjadi pertandingan yang dikembalikan oleh iterator saat itu disebut pertama kali.


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

@ LeakyNun benar-benar lupa keberadaan match\ o / menghemat banyak byte, terima kasih
Katenkyo

-1 untuk "indeks"
Leaky Nun


Saya tidak peduli, masih -1 untuk "indeks".
Leaky Nun

1

Javascript (menggunakan perpustakaan eksternal) (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]

Tautan ke lib: https://github.com/mvegh1/Enumerable/blob/master/linq.js

Penjelasan kode: Perpustakaan menerima string, yang akan diuraikan menjadi array char. Itu akan dipetakan ke objek yang menyimpan indeks dan char. Urutan dibagi menjadi beberapa bagian pada setiap kemunculan "". Selanjutnya disaring dengan memeriksa apakah indeks kursor terkandung dalam indeks minimum dan maksimum dari indeks berikutnya. Kemudian kita ambil urutan pertama. Kemudian kita mengubahnya kembali menjadi hanya array char. Lalu kami menggabungkan semua karakter dengan "" sebagai pembatas. Kemudian kami memvalidasi terhadap kata regex. Lalu kami mengambil pertandingan pertama.

masukkan deskripsi gambar di sini


Kata "kata" didefinisikan oleh regex (?<!\w)\w+(?!\w), di mana \wdidefinisikan oleh [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], atau "karakter alfanumerik di ASCII termasuk garis bawah".
Leaky Nun

Ketika saya menjalankan regex itu terhadap ab! Cd di regex101.com saya mendapatkan ini: Tidak ada grup pertandingan yang diekstraksi. Ini berarti bahwa pola Anda cocok tetapi tidak ada (menangkap (grup)) di dalamnya yang cocok dengan apa pun dalam string subjek. Mungkin saya membuat kesalahan di suatu tempat ...
applejacks01

Mengapa saya perlu menangkap sesuatu?
Leaky Nun

Saya tahu ini bukan tempat untuk belajar, tetapi saya mengatakan bahwa ketika saya menjalankan regex itu terhadap ab! Cd saya tidak mendapatkan apa-apa. Jadi mengapa 'ab' menjadi hasil yang benar?
applejacks01


1

Perl 6 , 34 byte

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

Cobalah online!

Kode kunci anonim yang memerlukan input kari, seperti f(n)(string).

Penjelasan:

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

Ruby , 30 byte

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

Cobalah online!

Pendekatan yang berbeda, hanya 1 byte lebih pendek dan 3 tahun kemudian. Kenapa tidak?


1

APL (NARS), 58 karakter, 116 byte

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

⍵ {⍵≤1: ⍵⋄m∊⍨⍵⊃⍺: ⍺∇⍵-1⋄⍵ + 1} ⍺ temukan di mana memulai string ... Cara menggunakan dan menguji:

  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)

Kursor diindeks 1 dan setelah karakter (seperti dalam kasus uji).

Cobalah online! Atau verifikasi semua kasus uji .

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

Semacam solusi konyol, tetapi pendekatan yang berbeda dari yang lain.

Mengambil input $asebagai indeks string berbasis 0 $n. Kemudian, kami menemukan batasan kata kami. Meskipun kami belum mencapai akhir string dan / atau kami masih mencocokkan karakter kata, kami ++$a. Lalu, karena fenceposting, kami atur $i=$a--. Selanjutnya, kami merangkak mundur, mengurangi $asampai itu baik0 atau kami menekan karakter non-kata. Kami kemudian mengiris string input berdasarkan pada dua demarkasi tersebut (dengan beberapa penambahan / pengurangan untuk memperhitungkan OBOE), dan -joinbersama-sama menghasilkan hasilnya.

Contohnya

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];}
  • memisahkan string dengan non-kata-karakter, mengingat posisi mereka ( 4== PREG_SPLIT_OFFSET_CAPTURE), loop melalui kata-kata sampai posisi tercapai.
  • String PHP diindeks 0, kursor sebelum karakter, tetapi mungkin sebelum atau sesudah kata

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

Diindeks 0.

Cari mundur ke karakter alfanumerik pertama dari indeks, lalu maju ke karakter alfanumerik terakhir setelah indeks. Mungkin ada cara yang lebih cerdas untuk melakukan ini.

Cobalah


@ LeakyNun _ditambahkan, saya tidak yakin mengapa saya akan mendapatkan kesalahan f('abc',1).
atlasologist

0

JavaScript (ES 6), 43 42 Bytes

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

JavaScript (ES 3), 65 Bytes

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

Pelabuhan @AndersKaseorg 's Pyth jawabannya .

1-diindeks seperti kasus uji tantangan.

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

ð«              # 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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.