การลบสตริง


37

วัตถุประสงค์

สร้างฟังก์ชั่นเพื่อย้อนกลับการต่อสตริง

อินพุต

สองสตริง (ช่องว่างตัวเลขและตัวอักษร) โดยที่หนึ่งควรถูกลบสำหรับอีกสาย

  • คุณสามารถสันนิษฐานได้ว่าสตริงที่จะลบจะไม่ใหญ่กว่าอีกอันหนึ่ง

เอาท์พุต

ผลที่ได้จากการลบ

การลบ

คุณควรลบหนึ่งสายจากจุดเริ่มต้นหรือจุดสิ้นสุดของสายอื่น หากสตริงนั้นมีอยู่ในการเริ่มต้นและในท้ายที่สุดคุณสามารถลบได้เพียงหนึ่งอันซึ่งจะถูกลบออกขึ้นอยู่กับคุณ
หากสตริงไม่ได้อยู่ในการเริ่มต้นหรือสิ้นสุดหรือไม่ใช่การจับคู่ที่แน่นอนมันเป็นการลบที่ไม่ถูกต้องและคุณควรส่งออกสตริงเดิม

กรณีทดสอบ

การลบที่ถูกต้อง

'abcde','ab' -> 'cde'
'abcde','cde' -> 'ab'
'abab','ab' -> 'ab'
'abcab','ab' -> 'abc' or 'cab'
'ababcde','ab' -> 'abcde'
'acdbcd','cd' -> 'acdb'
'abcde','abcde' -> ''
'abcde','' -> 'abcde'
'','' -> ''

การลบไม่ถูกต้อง (ส่งคืนสตริงต้นฉบับ)

'abcde','ae' -> 'abcde'
'abcde','aa' -> 'abcde'
'abcde','bcd' -> 'abcde'
'abcde','xab' -> 'abcde'
'abcde','yde' -> 'abcde'

อินพุตไม่ถูกต้อง (ไม่จำเป็นต้องจัดการ)

'','a' -> ''

นี่คือดังนั้นโค้ดที่สั้นที่สุดในหน่วยไบต์ชนะ!


4
ทำไมเป็นผลมาจากกรณีแรกไม่ได้cde? คุณหมายถึงอะไรที่ถูกต้อง? เราจำเป็นต้องตัดสินความถูกต้องของอินพุตหรือคุณหมายความว่าเราจะไม่ได้รับอินพุตที่ไม่ถูกต้องหรือไม่?
Leun Nun

7
ประณามคุณ, 'abcde','bcd' -> 'abcde'สำหรับการแก้ปัญหาของฉัน
John Dvorak

5
เราสามารถสันนิษฐานได้ว่าสตริงนั้นปลอดภัยสำหรับ regex (ช่องว่างระหว่างตัวอักษรและตัวเลข)?
John Dvorak

2
ฉันขอแนะนำ'ababcde', 'ab''abcde'เป็นกรณีทดสอบ อัลกอริทึมไร้เดียงสาบางอันล้มเหลว

2
@Rod คุณอาจลองตอบโต้ความท้าทาย "Reverse string concatenation"?
MD XF

คำตอบ:


19

Java 8, 46 45 44 40 ไบต์

-1 ไบต์ขอบคุณ TheLethalCoder

-1 ไบต์เพราะฉันโง่ (ขอบคุณ Rod!)

-4 ไบต์ต้องขอบคุณ Kevin Cruijssen

a->b->a.replaceFirst("^"+b+"|"+b+"$","")

ลองออนไลน์! (รวมถึงกรณีทดสอบทั้งหมด)

คำตอบ Java จริง ๆ แล้วภาษาอื่น ๆ อีกสองสามภาษา รอยยิ้ม (และตอนนี้มันเต้น JS!)


ใช้การแกงเพื่อบันทึกไบต์a->b->
TheLethalCoder

@TheLethalCoder ขอบคุณ
Okx

ทำไมคุณถึงทิ้งแฮชแมปที่ไม่ได้ใช้ในตัวอย่างออนไลน์ของคุณ?
Michael

คุณสามารถเปลี่ยนFirstไปAllสำหรับ -2 ไบต์ เนื่องจาก^และ$มันมักจะอยู่ที่ปลายหรือจุดเริ่มต้นของสตริงเสมอดังนั้นแม้ว่าจะมีการreplaceAllแทนที่เพียงครั้งเดียวเท่านั้น ลองที่นี่ PS: ฉันเพิ่มการนับจำนวนไบต์ก่อนหน้านี้ผ่านเข้าไปในคำตอบของคุณซึ่งเป็นสิ่งที่มักจะทำหลังจากการแก้ไขโค้ดกอล์ฟที่นี่ใน PPCG
Kevin Cruijssen

@KevinCruijssen ฉันรู้เกี่ยวกับการนัดหยุดงานเดาว่าฉันลืมเวลานี้ อย่างไรก็ตามถ้าฉันใช้AllแทนFirstสิ่งนี้จะกลายเป็นจริง:"abab" + "ab" -> ""
Okx

9

JavaScript (ES6), 41 ไบต์

s=>t=>s.replace(eval(`/^${t}|${t}$/`),'')

f("abab")("ab")จะเข้าทางดีความชอบไวยากรณ์คือ


3
ตอนนี้ทำไมฉันไม่เคยคิดที่จะใช้eval()สำหรับการสร้าง RegExes มาก่อน!
Shaggy

9

Brachylog (ลองออนไลน์!) ขนาด 12 ไบต์

~cpĊh.∧Ċtw|w

ลองออนไลน์!

รับค่าสตริงเพื่อลบออกจากอินพุตมาตรฐานและสตริงเพื่อลบเป็นอาร์กิวเมนต์บรรทัดคำสั่ง

คำอธิบาย

~cpĊh.∧Ċtw|w
~c            Split {the input} into pieces
  p           and (possibly) rearrange those pieces
   Ċ          such that there are two pieces
    h         and the first
     .        matches the command line argument
      ∧       then
         w    print
        t     the last
       Ċ      piece.
          |   If all else fails,
           w  print {the input}.


6

JavaScript (ES6), 76 70 45 41 ไบต์

s=>t=>s.replace(RegExp(`^${t}|${t}$`),"")

ลองมัน

f=
s=>t=>s.replace(RegExp(`^${t}|${t}$`),"")
o.innerText=f(i.value="abcde")(j.value="ab")
i.oninput=j.oninput=_=>o.innerText=f(i.value)(j.value)
<input id=i><input id=j><pre id=o>


2
new คุณไม่จำเป็นต้อง
programmer5000

@ programmer500 ฉันก็ยอมแพ้ที่จะทำสิ่งนี้เมื่อฉันเห็นรุ่นของ ETH! : D อัปเดตทันที ขอบคุณ
Shaggy



3

TI-Basic (TI-84 Plus CE), 63 ไบต์

Prompt Str0,Str2
inString(Str0,Str2
If Ans
sub(Str0,1,Ans-1)+sub(Str0,Ans+length(Str2),length(Str0)-Ans+1-length(Str2→Str0
Str0

ฉันมีคำถามทำไมคุณไม่ใช้ Str1 เป็นตัวแปร
Zacharý

@ Zacharýฉันคิดว่าฉันมีสิ่งที่เก็บไว้ในเวลานั้น ฉันจำไม่ได้จริงๆ
pizzapants184

Ansแม้จะอ้างถึงอะไรในบรรทัดที่สี่?
Zacharý

@ Zacharý Ansหมายถึงค่าที่ประเมินล่าสุดดังนั้นในกรณีนี้มันหมายถึงค่าที่ส่งคืนโดยinString(ซึ่งเป็นดัชนีของสตริงย่อยStr2ในสตริงStr0หรือ 0 หากสตริงย่อยไม่ปรากฏขึ้น ถ้างบไม่ได้ปรับเปลี่ยนค่าของ Ans Ansดังนั้นในบรรทัดที่สี่ดัชนียังคงอยู่ใน
pizzapants184

โอ้ฉันลืมวิธีการinStringทำงาน กอล์ฟดี!
Zacharý

3

Mathematica, 162 ไบต์

(c=Characters;a=c@#;b=c@#2;l=Length;t={};If[l@Intersection[a,b]==l@b,If[MemberQ[Partition[a,l@b,1],b],t=a;Table[t=DeleteCases[t,b[[i]],1,1],{i,l@b}]],t=a];""<>t)&

ทดสอบรูปแบบการป้อนข้อมูล ["abcde", "ab"]


1
ทางออกที่ดี! คุณสามารถบันทึกไบต์โดยใช้#แทน#1- พวกเขามีความหมายเหมือนกัน นอกจากนี้แทนที่จะใช้StringJoin@tคุณสามารถโกงได้โดยเข้าร่วมสตริงที่ว่างเปล่าด้วย""<>tซึ่งจะรวมทุกอย่างtเข้าด้วยกันโดยอัตโนมัติ คุณเคยเห็นหน้าเคล็ดลับการเล่นกอล์ฟ Mathematicaหรือไม่?
ไม่ใช่ต้นไม้

มีอีกสองสามสิ่งที่คุณสามารถทำได้เพื่อบันทึกไบต์ (ฉันไม่คิดว่าคุณไม่จำเป็นต้องกำหนดt={};ในตอนเริ่มต้น) แต่อาจจะง่ายกว่าที่จะใช้วิธีการที่แตกต่างกันโดยสิ้นเชิง - คุณลองใช้StringReplaceฟังก์ชั่น?
ไม่ใช่ต้นไม้

คุณได้รับอนุญาตให้ใช้อาร์เรย์เป็นสตริงดังนั้นคุณไม่ต้องการจริงๆc=Characters;a=c@#;b=c@#2;
JungHwan Min

นอกจากนี้ยังเป็นl@Intersection[a,b] l[a∩b]
JungHwan Min

3

Python, 69 68 64 57 51 45 ไบต์

สิ่งนี้กลายเป็นโซลูชันที่แตกต่างอย่างสิ้นเชิงกับ Regex

ขอบคุณValue Inkขนาด -2 ไบต์!
และเฟลิเป้นาร์ดีบาติสตาสำหรับขนาดใหญ่ -6 ไบต์!

import re
lambda s,c:re.sub(c+'$|^'+c,'',s,1)

ลองออนไลน์!


สำหรับ -2 ไบต์:re.sub(c.join("^|$"),'',s,1)
ค่าหมึก

1
สำหรับ -6 ไบต์:c+'$|^'+c
Felipe Nardi Batista

3

ทุบตี ,66 61 49 ไบต์

case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac

ลองออนไลน์!

น้อย golfed:

a=$1;
case $1 in 
    *$2)  c=${a%$2};;       
    $2*)  c=${a#$2};;
      *)  c=$1;;
esac;
echo $c

ใช้กรณีเพื่อทดสอบจุดเริ่มต้นหรือจุดสิ้นสุดและการแทนที่หน้านำหน้า / ส่วนต่อท้ายของอาร์เรย์


1
ใช้ดีcaseแต่ยาวเกินความจำเป็น รูปแบบที่ 2 และ 3 *)c=${1#$2};;อาจจะรวมเป็นหนึ่งเดียว: จากนั้นมีเพียง 2 สาขาจะสั้นลงechoแต่ละโดยตรงแทนการใช้ตัวแปร:$c case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esacหรือคุณอาจจะให้ใช้มัน แต่ไม่:case c=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c
ผลิต

3

APL (Dyalog) , 31 30 ไบต์

-1 ขอบคุณที่Zachary

จริงๆแล้วใช้การต่อข้อมูลย้อนกลับ (เช่นการผกผัน)! รับสายเดิมเป็นอาร์กิวเมนต์ด้านซ้ายและสิ่งที่จะลบเป็นอาร์กิวเมนต์ที่ถูกต้อง

{0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}

ลองออนไลน์!

Ungolfed:

{
    0::⍺{          if an error happens, apply the following function on the arguments
        0::⍺           if an error happens, return the left argument unmodified
        ,∘⍵⍣¯1⊢⍺       inverse-append right argument on left argument
        }⍵
    ⍵,⍣¯1⊢⍺       inverse-prepend the right argument on the left argument
}

ตำนาน:

{} ฟังก์ชั่นไม่ระบุชื่อ

 อาร์กิวเมนต์ที่เหลือของฟังก์ชันปัจจุบัน

 อาร์กิวเมนต์ที่ถูกต้องของฟังก์ชันปัจจุบัน

0::…หากมีข้อผิดพลาดเกิดขึ้นให้ดำเนินการสิ่งนี้…

⍣¯1⊢ ผกผัน

,∘⍵ ต่อกันด้านขวา

⍵, เรียงต่อกันทางซ้าย


{0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}ฉันคิดว่าคุณสามารถบันทึกไบต์ด้วย
Zacharý

@ Zacharýใช่ขอบคุณ
อดัม



2

Haskell , 49 ไบต์

f s a b|s==b=a|a/=b,h:t<-a=f(s++[h])t b|1<3=s
f""

ลองออนไลน์! การใช้งาน: f"" "abcdef" "ab". อีกวิธีหนึ่งคือการกำหนดและการใช้งานเช่น(-)=f"" "abcdef" - "ab"

โซลูชันที่ไม่ใช้ regex นี้ทำงานโดยการแยกสตริงซ้ำใน pre- และ postfix ทั้งหมดของมันและตรวจสอบว่าสตริงที่จะถูกแทนที่ตรงกับหนึ่งในนั้นหรือไม่




1

Ruby (แลมบ์ดานิพจน์), 29 ไบต์

->a,b{a.sub /^#{b}|#{b}$/,""}

Yay สำหรับการแก้ไข regex! ต้องใช้ตัวย่อยแบบปลอดภัย regex แต่ก็ไม่เป็นไรตามความท้าทาย


1

Tcl , 37 ไบต์

proc s {a b} {regsub "^$b|$b$" $a {}}

ลองออนไลน์! (ตอนนี้ทำการทดสอบทั้งหมด)

Tcl ตรงไปตรงมา proc s {a b}กำหนดฟังก์ชั่นที่มีชื่อsที่ใช้พารามิเตอร์และa ทดแทนซึ่งเป็นสตริงที่ว่างเปล่าสำหรับค่าของเมื่อมันที่เริ่มต้นหรือจุดสิ้นสุดของ ผลตอบแทนคือความหมายโดยนัยbregsub{}ba


1

C, 96 ไบต์

มันเป็นความรู้ทั่วไปที่การจัดการสตริงใน C นั้นยุ่งยากเนื่องจากการเล่นกอล์ฟส่วนต่อขยายจะเป็นแนวเขตแดนแบบโซคิสต์ ฟังดูเป็นไรสำหรับฉัน

f(a,b,t,l)char**a,*b,*t;{t=*a;l=strlen(b);bcmp(t,b,l)?bcmp(t+=strlen(t)-l,b,l)||(*t=0):(*a+=l);}

หนึ่งในโปรแกรมที่อ่านได้น้อยกว่าที่ฉันเขียน รับค่าอินพุตสองค่า (แม้จะมีฟังก์ชั่นการค้นหา) การchar**ชี้ไปที่สตริงเพื่อ deconcatenate และ a char*ซึ่งเป็นสตริงที่จะลบ ตัวชี้อินพุตถูกแก้ไขในสถานที่และกลายเป็นเอาต์พุต (กรณีที่เกี่ยวกับหน่วยความจำรั่ว)

ตัวอย่างการใช้งาน:

char *a = malloc(6);
strcpy(a, "abcde");
char *b = malloc(4);
strcpy(b, "abc");
f(&a,b);
printf("%s\n", a); // "de"

1

AWK , 21 32 ไบต์

{sub("^"$2"|"$2"$",z,$1);$0=$1}1

ลองออนไลน์!

ส่งต้นฉบับอย่างไร้เดียงสาแทนที่ข้อความภายในสตริงแรกไม่เพียง แต่ที่จุดเริ่มต้นหรือสิ้นสุด

{sub($2,z,$1);$0=$1}1

ลองออนไลน์!

เดิมทีพยายามโดยไม่มีเครื่องหมายปีกกา แต่จำเป็นต้องใช้เทคนิคในการพิมพ์บรรทัดว่างเปล่าและหรือไม่มีการจับคู่ซึ่งจบลงด้วยการเพิ่มไบต์มากกว่ารุ่นนี้


1

R, 20 42 41 ไบต์

pryr::f(sub(sprintf('^%s|%s$',b,b),'',a))

-1 ไบต์ต้องขอบคุณ MickyT!

ส่งคืนฟังก์ชันที่ไม่ระบุชื่อ (ซึ่งมีอาร์กิวเมนต์ตามลำดับb,a) a-bคำนวณความแตกต่างสตริง เป็นเปลี่ยนตัวง่ายๆที่แลกเปลี่ยนเกิดขึ้นครั้งแรกของรูปแบบที่มีในกรณีนี้สตริงที่ว่างเปล่าsub ''สร้าง regex ด้วยsprintfเพื่อจับคู่เฉพาะที่จุดเริ่มต้นและจุดสิ้นสุดของสตริง ต้องมีpryrแพ็คเกจที่จะติดตั้ง

บนลิงก์ TIO ใช้function(a,b)นิยามverbose มากขึ้นสำหรับฟังก์ชันสำหรับไบต์ที่สี่เพิ่มเติม

ลองออนไลน์!


1
เกี่ยวกับ'abcde','bcd' -> 'abcde'กรณีอะไร
Jonathan Allan

" subเป็นการทดแทนอย่างง่ายที่จะสลับการเกิดขึ้นครั้งแรกbในa": การสลับนี้จะไหมถ้าสตริงที่สองอยู่ตรงกลางของสตริงแรก?
TheLethalCoder

ฉันอ่านคำถามผิด! อุ่ย ขอบคุณสำหรับการจับ!
Giuseppe

คุณสามารถรับ 1 ไบต์ด้วยsprintf('^%s|%s$',b,b)
MickyT

@MickyT ขอบคุณ! แก้ไขแล้ว.
Giuseppe

1

เสียงกระเพื่อมสามัญ 121 ไบต์

(lambda(x y)(cond((equal(#1=subseq x 0 #3=(length y))y)(#1#x #3#))((equal(#1#x #2=(-(length x)#3#))y)(#1#x 0 #2#))(t x)))

ลองออนไลน์!

เสียงกระเพื่อมสามัญคำปกติ!

เวอร์ชันที่ไม่ถูกปรับแต่ง:

(defun f(x y)
  (cond ((equal (subseq x 0 (length y)) y)               ; if x starts with y
         (subseq x (length y)))                          ; return rest of x
        ((equal (subseq x (- (length x) (length y))) y)  ; if x ends with x
         (subseq x 0 (- (length x) (length y))))         ; return first part of x
        (t x)))                                          ; else return x


1

Powershell, 34 40 ไบต์

+6 ไบต์เมื่อInvalid Subtractionเพิ่มกรณีทดสอบ

param($s,$t)$s-replace"^$t(?!.*$t$)|$t$"

หมายเหตุ:

นิพจน์ regexp ^$t|$t$ไม่ทำงานตามที่คาดไว้: มันแทนที่ทั้งคู่ที่ตรงกันแทนหนึ่งรายการ (เปิดแฟล็กgเสมอ) ดังนั้นเราถูกบังคับให้ใช้กลุ่ม lookahead เชิงลบ

สคริปต์ทดสอบ:

$f = {
    param($s,$t)$s-replace"^$t(?!.*$t$)|$t$"
}

@(
    ,('abcde','ab', 'cde')
    ,('abcde','cde', 'ab')
    ,('abab','ab', 'ab')
    ,('abcab','ab', 'abc', 'cab')
    ,('ababcde','ab', 'abcde')
    ,('acdbcd','cd', 'acdb')
    ,('abcde','abcde', '')
    ,('abcde','', 'abcde')
    ,('','', '')

    ,('abcde','ae', 'abcde')
    ,('abcde','aa', 'abcde')
    ,('abcde','bcd', 'abcde')
    ,('abcde','xab', 'abcde')
    ,('abcde','yde', 'abcde')

    ,('','a', '')
) | % {
    $s,$t,$e = $_
    $r = &$f $s $t
    "$($r-in$e): $r"
}

เอาท์พุท:

True: cde
True: ab
True: ab
True: abc
True: abcde
True: acdb
True:
True: abcde
True:

0

QBIC , 57 ไบต์

นี่มันยุ่งเหยิงใน QBIC / QBasic ...

B=@ `+B┘x=instr(;,;)~x|?_t_sB,x-1|+_sB,x+_lC|,_lB|||\?B

B=@ `+B          Prepend a string to B$. Thisis a hack to avoid errors with 
                 removing substrings stating at index 1
┘                Line-break in QBasic output
       (;,;)     Read the string (B$) and the to-be-removed substring (C$)
x=instr          And make x to be the starting index of the first C$ in B$
~x|              IF X <> 0 (ie C$ is present in B$)
?                PRINT
 _t                trimmed version (drops the prepended space)
  _sB,x-1|+        of a substring from 1 to x (the start of C$) -1
  _sB,x+_lC|,_lB   and the rest of the string, starting after C$
                     _l takes the length of a string
  |||              End TRIM, end Substring, end Length
\?B              When missing C$, just print B$


0

ฉันเริ่มอ่านคำแนะนำผิด ขอบคุณØrjan Johansen ที่ชี้ความผิดพลาดของฉัน!

PowerShell , 46 51 ไบต์

Function F($o,$a){([regex]"^$a").replace($o,'',1);}

ลองออนไลน์!


สิ่งนี้ล้มเหลวในกรณี 'abcde' 'bcd'
Ørjan Johansen

ฉันเห็นผลลัพธ์ที่คาดหวังจากกรณีทดสอบ - TIO ที่นี่
Jeff Freeman

มันเป็นกรณีทดสอบที่ระบุไว้ของ OP และผลลัพธ์ควรเป็นabcde- bcdไม่เกิดขึ้นที่ปลายทั้งสองด้านของสตริง
Ørjan Johansen

คุณถูก. ฉันอ่านคำแนะนำผิด ขอบคุณที่ชี้นำ!
Jeff Freeman

0

Excel, 129 ไบต์

=IFERROR(IF(FIND(B1,A1)=1,SUBSTITUTE(A1,B1,"",1),IF(FIND(B1,A1,LEN(A1)-LEN(B1))>LEN(A1)-LEN(B1),LEFT(A1,LEN(A1)-LEN(B1)),A1)),A1)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.