Belirli bir dizede verilen dizinin etrafındaki kelimeyi seçme


20

Windows'da, bir metne çift tıkladığınızda, metindeki imlecinizin etrafındaki kelime seçilir.

(Bu özelliğin daha karmaşık özellikleri vardır, ancak bu sorun için uygulanması gerekmeyecektir.)

Örneğin, |imleciniz içeri girsin abc de|f ghi.

Ardından, çift tıklattığınızda alt dize defseçilir.

Giriş çıkış

Size iki giriş verilecektir: bir dize ve bir tam sayı.

Göreviniz, tamsayı tarafından belirtilen dizinin etrafındaki dizenin word-alt dizesini döndürmektir.

İmleciniz, belirtilen dizindeki dizedeki karakterden hemen önce veya hemen sonra olabilir .

Daha önce kullanırsanız , lütfen cevabınızda belirtin.

Özellikler (özellikler)

Dizinin bir sözcüğün içinde olması garanti edilir, bu nedenle abc |def ghiveya gibi kenar durumu yoktur abc def| ghi.

Dize yalnızca yazdırılabilir ASCII karakterleri içerecektir (U + 0020 - U + 007E).

Kelime "sözcüğü" regex ile tanımlanır (?<!\w)\w+(?!\w), \wtarafından tanımlanır [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], ya da "alt çizgi dahil ASCII alfanümerik karakterden".

Dizin 1 dizinli veya 0 dizinli olabilir.

0 dizinli kullanıyorsanız, lütfen cevabınızda belirtin.

testcases

Test senaryoları 1 dizinlidir ve imleç belirtilen dizinden hemen sonradır .

İmleç konumu yalnızca gösterim amaçlıdır ve çıktı alınması gerekmez.

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
Dize yeni satırlar içerebilir mi?
orlp

@orlp Zorluk, girdiyi yazdırılabilir ASCII ile sınırlamak için düzenlendi, böylece girdi yeni satırlar içermeyecek.
FryAmTheEggman

Test vakalarınızda boşluklardan başka herhangi bir sınırlayıcı yoktur. Peki bir kelimeye ne dersiniz we're?
orlp

2
Ne "ab...cd", 3dönmeli?
Titus

5
@Titus "Endeksin bir kelimenin içinde olması garanti ediliyor"
Martin Ender

Yanıtlar:


10

V , 10, 9 7 bayt

À|diwVp

Çevrimiçi deneyin!

Bu yanıt 1 tabanlı dizinleme kullanır.

Başlığın söylediklerini tam olarak yaparsak bu daha kısa olabilir: " Bir dizede verilen dizinin etrafındaki kelimeyi seçin ". Yapabilirdik

À|viw

Bu kelimenin tam anlamıyla kelimeyi seçer, ancak maalesef çıktıyı hiç değiştirmez. Bu nedenle, bir kayıt defterine keserek, metnin geri kalanını silerek ve ardından kaydı tekrar yapıştırarak çalışmasını sağlamak için biraz geçici bir çözüme ihtiyacımız var.

Açıklama:

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

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 girdisinin 0 tabanlı dizin, ardından bir boşluk veya satırsonu, ardından dize olmasını bekler. Bir kelime için maksimum uzunluk 99 karakterdir. Örneğin:

2 abc def

C ve perl'in dize tabanlı bir mücadeleye bağlı olduğunu görmek gerçekten harika. :D
DJMcMayhem

Giriş dizesi 100 karakterden uzun olabilir mi?
Leaky Nun

@LeakyNun Evet, ancak bir kelime 100 karakterden uzun olamaz.
orlp

Bu gereksinimi cevabınızın içine koymak ister misiniz?
Leaky Nun

@DrGreenEggsandIronMan Çok kötü cevabımı düzeltmek zorunda kaldım çünkü
boşlukta

4

C (gcc), 94 bayt

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

Sıfır dizinli, önce dizini alan bir işlevi tanımlar.


Bence isalnum(*++p)|*p==95tanımsız bir davranış.
owacoder

@owacoder Ama önemli olan şey, gcc'nin çalışan bir yürütülebilir dosyayı tükürmesidir. *++p^95?isalnum(*p):1bir bayt daha uzun, ancak her derleyici üzerinde çalışıyor.
orlp

Ben önde gelen alan bir yazım hatası olduğunu varsayalım? Ayrıca, burada tembel bir IDEone bağlantısı var.
FryAmTheEggman

isalnum(*++p)||*p==95ayrıca bir bayt için de çalışır.
owacoder

@FryAmTheEggman Evet, düzeltildi.
orlp

3

Retina, 22

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

Çevrimiçi deneyin! veya tüm test senaryolarını doğrulayın . Normal program, imleç konumunu tek tek alır ve ardından bir satırsonu ve sonra dize alır. Test takımında her satır modunda çalıştırılacak ek kod vardır ve \ayırıcı olarak a kullanır ve kolaylık sağlamak için ondalık kullanır.

İmleç konumunu bulmak için dengeleme gruplarını kullanır, sonra bir kelime sınırına kadar geriye doğru izler. Metni sözcüğe kadar ve sonra sözcükten sonra siler.


2

C, 115 bayt

İşlev f()parametre olarak dize ve dizin (1 dizinli) gerektirir ve sonucu stdout'a yazdırır. İmleç belirtilen karakterden sonra olmalıdır.

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 bayt

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

Dizeyi imleç noktasında (1 dizinli karakterden sonra aynı şekilde çalışan 0 dizinli karakterden önce olan) dilimler, ardından bitişik sözcük parçalarını ayıklar ve birleştirir. Hatta imleç bir kelimenin başında, sonunda veya hiçbir yerinde olmadığında bile mantıklı bir sonuç verir.


Son regex'te * ihtiyacınız var mı?
Charlie Wynn

@CharlieWynn Evet, aksi takdirde ikinci test çantası yalnızca geri döner de.
Neil

whoops, koştuğum testlerle şanssız
Charlie Wynn

2

Java 8, 86 78 bayt

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

Test senaryolarıyla başa çıkma:

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

Dizeyi alfasayısal olmayan karakterlere böler, ardından negatif olana kadar her alt dizenin uzunluğunu, artı 1 belirtilen konumdan çıkarmaya devam eder. Yinelenen alfasayısal olmayan herhangi bir öğe boş dize olarak temsil edildiğinden, çıkarma mantığı önemli ölçüde daha kolaydır.

Bu kod kapsamlı bir şekilde test edilmez, bu yüzden birinin bunu kırabileceğini görmek istiyorum. Ayrıca, bunun Java kodu olduğu düşünüldüğünde, buradaki en uzun cevap nasıl değildir? : P


Neredeyse üç yıl geçtiğini biliyorum, ama bir curved lambda ifadesi (yani ) kullanarak (s,p)->olabilir . Ek olarak, Java 10'a geçildiyse şimdi olabilir , ancak bu elbette mevcut değildi. Ne olursa olsun, güzel cevap. Geçmişte bir yerde zaten güncellediğimi görüyorum. :)s->p->java.util.function.Function<String, java.util.function.Function<String, String>> fStringvar
Kevin Cruijssen

2

Pyth, 16 bayt

+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

Çevrimiçi deneyin



2

Pyke, 19 bayt

#Q;cjmli<i+s)lttjR@

Burada deneyin!

Q;İlk girişin doğru bir şekilde yerleştirildiğinden emin olmak için op-yok olarak kullanır

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

Bağlantınızı tıkladığımda 504 hatası alıyorum.
Leaky Nun

@LeakyNun Evet, yazarken kazara öldürdüm, bu yüzden localhost bağlantısı vardı, geri dönecek
Mavi


1
Programınız, N kelimesinin seçilen kelime olduğu yerde N çıktısı alıyor gibi görünüyor, ancak tam kelimeye ihtiyacımız var
Value Ink

2

Python 2, 70 66 bayt

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

Dizeyi sözcük olmayan ayırıcılarla böler, bir kez orijinal dizgide imleç dizinine, sonra da imleç dizininden başlayan dizgiye böler. Sol bölümün son öğesini ve sağ bölümün ilk öğesini döndürür. Leaky Nun'e 4 bayt kazandığı için teşekkürler!


1

Clojure, 92 bayt

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

İlk olarak, konumdaki giriş dizesini kiki dizeye böler . Sonra bu dizeler için oluşumları bulmak "\w+"ve liste olarak döndürür. Ardından, ilk listenin son öğesini ve ikinci listenin ilk öğesini birleştirin.

Çevrimiçi görün: https://ideone.com/Dk2FIs


1

JavaScript (ES6), 52 bayt

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


Neden (\\W+|^)olmasın(\\W|^)
l4m2

1

Lua, 71 67 Bayt

Woohoo, Lua en uzun çözüm değil! Python'un arkasında hala bir bayt var, ama bunu nasıl golf oynayacağını bilmiyorum. Dizinler 1 tabanlıdır.

@LeakyNun bana varlığını hatırlatan string.match4 bayt kurtardı

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

Yaşlı 71

Not: Açıklamalar hala buna dayanmaktadır, çünkü yeni açıklama için de geçerlidir, ancak hakkında ek bilgiler içerir. gmatch

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

açıklama

İlk olarak, içine argümanları açmak gve honlar daha kısa olduğu içinarg[x]

g,h=...

Sonra, imlecin önündeki ve sonrasının parçasının kontansasyonu olan çıktımızı inşa ederiz.

Dizenin ilk kısmı

g:sub(1,h)

Kelimeyi bunun sonunda bulmak istiyoruz, bu yüzden fonksiyonu kullanıyoruz string.gmatch

:gmatch"[%a_]*$"

Bu desen 0..n, dizenin sonundaki alfabe + alt çizgi karakter kümesiyle eşleşir . gmatcheşleşme listesinde bir işlev biçiminde bir yineleme döndürür (kapatma ilkesini kullanarak), bu yüzden kelimemizin ilk bölümünü almak için bir kez yürütürüz

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

Sözümüzün ikinci bölümünü aynı şekilde alıyoruz

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

Belirtmek zorunda olduğumuz tek fark, dizenin başlangıcında eşleşmek istediğimizi (kullanarak [^%a_]*), çünkü ilk kez çağrıldığında yineleyici tarafından döndürülen eşleşme olacaktır.


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

@LeakyNun, match\ o / varlığını tamamen unuttu, çok bayt kurtardı, teşekkürler
Katenkyo

Dizinleri için -1
Leaky Nun


Umurumda değil, "dizinler" için hala -1.
Leaky Nun

1

Javascript (harici kitaplık kullanarak) (168 bayt)

(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 bağlantısı: https://github.com/mvegh1/Enumerable/blob/master/linq.js

Kod açıklaması: Library, karakter dizisine ayrıştırılan bir dizeyi kabul eder. İndeksi ve karakteri saklayan bir nesneye eşlenir. Dizi "" nin her oluşumunda alt dizilere bölünür. Sonraki diziler, imleç dizininin dizinin min ve maks dizininde olup olmadığını kontrol ederek filtrelenir. Sonra ilk alt diziyi alırız. Sonra sadece bir char dizisine dönüşüyoruz. Sonra tüm karakterleri ayırıcı olarak "" ile birleştiririz. Sonra regex kelimesine karşı onaylıyoruz. Sonra ilk maçı yapacağız.

enter image description here


Kelime "sözcüğü" regex ile tanımlanır (?<!\w)\w+(?!\w), \wtarafından tanımlanır [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], ya da "alt çizgi dahil ASCII alfanümerik karakterden".
Leaky Nun

Ben regex101.com ab! Cd karşı bu regex çalıştırdığınızda: Bunu elde: Hiçbir maç grupları çıkarıldı. Bu, deseninizin eşleştiği ancak içinde konu dizesinde eşleşen hiçbir (yakalama (grup)) olmadığı anlamına gelir. Belki bir yerde bir hata yapıyorum ...
applejacks01

Neden bir şey yakalamam gerekiyor?
Leaky Nun

Bu öğrenilecek yer değil biliyorum, ama söylüyorum ki bu regex ab! Cd karşı çalıştırdığımda hiçbir şey alamadım. Öyleyse neden 'ab' doğru çıktı olsun ki?
applejacks01


1

Perl 6 , 34 bayt

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

Çevrimiçi deneyin!

Anonim kod bloğu, giriş gibi f(n)(string) .

Açıklama:

->\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 karakter, 116 bayt

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

⍵ {⍵≤1: ⍵⋄m∊⍨⍵⊃⍺: ⍺∇⍵-1⋄⍵ + 1} ⍺ dizeyi nereden başlatacağınızı bulun ... Nasıl kullanılır ve test edilir:

  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 bayt

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

İmleç 1 dizinli ve karakterden sonra (test durumlarında olduğu gibi).

Çevrimiçi deneyin! Veya tüm test senaryolarını doğrulayın .

'\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 +, 103101 bayt

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

Bir tür aptalca çözüm, ama diğerlerinden farklı bir yaklaşım.

Girdiyi $adizenin 0 tabanlı dizini olarak alır $n. Sonra, sözümüzün sınırlarını buluruz. Dizenin sonuna gelmemiş olsak da ve / veya hala kelime karakterleriyle eşleşmekteyiz, biz ++$a. Sonra, çit direği nedeniyle yola çıktık $i=$a--. Sonra, geriye doğru tararız, $aya 0da bir kelime karakteri olmayana kadar azalırız . Daha sonra, giriş dizesini bu iki sınırlamaya (OBOE'yi hesaba katmak için bazı artışlar / düşüşlerle) ve -joinsonucu üretmek için birlikte dilimliyoruz .

Örnekler

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 bayt

function f($s,$p){foreach(preg_split('#\W+#',$s,-1,4)as$m)if($m[1]+strlen($m[0])>=$p)return$m[0];}
  • dizeyi sözcüklerini olmayan karakterlerle böler ve konumlarını hatırlar (4 == PREG_SPLIT_OFFSET_CAPTURE) ulaşılana kadar sözcükler arasında dolaşır.
  • PHP dizeleri 0 dizinli, karakterden önce imleçtir, ancak sözcükten önce veya sonra olabilir

0

Python 3, 112140 bayt

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

Dizinden ilk alfasayısal karakterden geriye doğru arama yapar, ardından dizinden sonraki son alfasayısal karaktere gider. Muhtemelen bunu yapmanın daha akıllı bir yolu var.

Dene


@LeakyNun _eklendi, neden f('abc',1)olsa bir hata alacağımdan emin değilim .
atlasologist

0

JavaScript (ES 6), 43 42 Bayt

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

JavaScript (ES 3), 65 Bayt

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

0

05AB1E , 14 bayt

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

Port @AndersKaseorg 'Pyth cevabı s .

Zorlama testi vakaları gibi 1 endeksli.

Çevrimiçi deneyin veya tüm test senaryolarını doğrulayın .

Açıklama:

ð«              # 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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.