Nối và xóa


14

Cho một dòng chỉ bao gồm các chữ cái, xử lý như sau:

  • Bạn duy trì một chuỗi trống lúc đầu.
  • Nếu ký tự đầu vào tiếp theo nằm trong chuỗi, hãy xóa nó khỏi chuỗi.
  • Nếu ký tự đầu vào tiếp theo không có trong chuỗi, hãy thêm nó vào chuỗi.

Xuất trạng thái cuối cùng của chuỗi.

Bạn có thể giả định rằng đầu vào bao gồm ít nhất một ký tự (nghĩa là không trống), nhưng không có gì đảm bảo rằng đầu ra không trống.

Mã giả (Hãy thoải mái chơi gôn này):

str = EMPTY
for each character ch in input
  if ch exists in str
    remove all ch from str
  else
    append ch to str
print str

Đầu vào khớp với biểu thức chính quy ^[A-Za-z]+$.

Các trường hợp thử nghiệm mẫu:

ABCDBCCBE -> ADCBE
ABCXYZCABXAYZ -> A
aAABBbAbbB -> aAbB
GG -> (empty)

Đầu vào có thể được cung cấp theo bất kỳ cách áp dụng nào, nhưng nó phải được coi là một chuỗi và tương tự cho đầu ra. Chương trình không nên thoát với một lỗi.

Chương trình ngắn nhất trong mỗi ngôn ngữ sẽ thắng!

Thêm (Tùy chọn): Vui lòng giải thích cách chương trình của bạn hoạt động. Cảm ơn bạn.


Có thể dòng trống?
dùng202729

1
@ user202729 Không. Tôi đã thay đổi một chút (nó không làm mất hiệu lực bất kỳ câu trả lời nào) vì vậy đầu vào không bao giờ trống.
iBug

1
Vậy tại sao bạn từ chối đề xuất chỉnh sửa (liên kết) của ais523 ?
dùng202729

Câu trả lời:


10

Haskell , 44 42 byte

foldl(#)""
s#x|z<-filter(/=x)s=z++[x|z==s]

Hãy thử trực tuyến! Chỉnh sửa: -2 byte nhờ Zgarb!

Giải trình:

Dòng thứ hai xác định một hàm (#)lấy một chuỗi svà một ký tự xvà thực hiện loại bỏ hoặc chắp thêm. Điều này đạt được bằng cách filtering ra mỗi lần xuất hiện của xtrong s, kết quả là chuỗi z. Nếu xkhông xảy ra s, thì zbằng sz++[x|z==s]mang lại chuỗi gốc có xnối thêm. Mặt khác [x|z==s]mang lại chuỗi trống và chỉ có chuỗi được lọc được trả về.

foldl(#)""là một hàm ẩn danh nhận một chuỗi và thêm một ký tự sau chuỗi khác ban đầu trống ""với hàm (#).


2
42 byte bằng cách sử dụng lại bộ lọc.
Zgarb


8

J , 21 19 byte

#~~:&.|.(2|*)1#.=/~

Làm thế nào nó hoạt động:

=/~ - tạo một bảng bằng nhau của các ký tự trong chuỗi:

   a =. 'ABCXYZCABXAYZ'
   ]b =: =/~ a 
1 0 0 0 0 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 1
0 0 1 0 0 0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 0 1 0 0 1 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 1

1#. - tổng của mỗi hàng theo chuyển đổi cơ sở 1 (số lần xuất hiện của chữ cái)

   ]c =: 1#. b
3 2 2 2 2 2 2 3 2 2 3 2 2

~:&.|- đảo ngược, sau đó áp dụng rây nub (là char duy nhất) và đảo ngược lại. Vì vậy, tôi tìm thấy lần xuất hiện cuối cùng của các ký tự trong chuỗi:

   ]d =. ~:&.|. a
0 0 0 0 0 0 1 0 1 1 1 1 1

* - nhân số đếm với 1 cho vị trí cuối cùng của ký tự trong sring, bằng 0 nếu không, được tính bằng cách trên ~:&.|

   ]e =. c * d
0 0 0 0 0 0 2 0 2 2 3 2 2

2| - modulo 2 (đặt thành 0 vị trí của các ký tự có số chẵn):

   ]f =. 2| e 
0 0 0 0 0 0 0 0 0 0 1 0 0

#~- sao chép đối số bên trái arg. lần (~ đảo ngược vị trí của các đối số)

]f # a A

Hãy thử trực tuyến!


6

Brainfuck, 95 byte

,[<<<[[->+>>>+<<<<]>>>[-<+<->>]<<[[-]<]>[[-]>>[-]>[[-<+>]>]<<[<]<<]<<]<[->>>>[-]<<<]>>>>[->+<]>>[>]>>,]<<<[.<]

Dùng thử trực tuyến

Làm thế nào nó hoạt động

, Gets first input
[ Starts loop
    <<< Go to start of string
    [ Loop over the string
        [->+>>>+<<<<] Duplicates the current char of the string
        >>>[-<+<->>] Duplicates and subtracts the inputted char from the duplicate of the string char
        <<[[-]<] If the char is different to the input, remove the difference
        > If the char is the same
        [
            [-]>>[-]>[[-<+>]>]<<[<]<< Remove the char from the string and sets the inputted char to 0
        ]
        << Moves to the next char of the string
    ]
    >>>[->+<] adds the inputted char to the string
    >>[>]>>, gets the next input
]
<<<[.<] prints the string



2

R , 92 84 77 byte

for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='')

Hãy thử trực tuyến!

-15 byte nhờ djhurio

Giải trình

djhurio cung cấp một câu trả lời R xuất sắc tránh một forvòng lặp - vì các lập trình viên R theo bản năng làm theo quy tắc (bao gồm cả bản thân tôi). Đây là một câu trả lời R sử dụng một forvòng lặp (và lưu một vài byte trong quy trình).

  • x=scan(,''); - gán đầu vào vào biến x
  • y=''; - tạo một chuỗi rỗng trong một biến gọi là y
  • for(i in el(strsplit(x,'')))- cho mọi nhân vật itrongx
  • y=c(y[y!=i],if(!i%in%y)i)- gán cho ymọi phần tử ykhông bằng i, nối thêm inếu ichưa có trongy
  • cat(y,sep='')- in các phần tử ykhông có khoảng cách giữa chúng

Ghi chú

Nếu bạn nhấp vào liên kết TIO ở trên, bạn sẽ tìm thấy trong tiêu đề library(methods); điều này là để xử lý lỗi djhurio gặp phải liên quan đến el()chức năng - chức năng được cung cấp bởi methodsgói, trong bất kỳ phiên bản R nào tôi đã sử dụng, được tải theo mặc định, nhưng vì bất kỳ lý do gì không phải do TIO. Nếu library(methods)được xóa khỏi tiêu đề và unlistđược thay thế cho el, tôi có được bốn byte, nhưng djhurio cũng vậy , đặt số byte của chúng tôi lần lượt là 96 88 và 99.


Đẹp một. Không bao giờ nghĩ cho vòng lặp sẽ ngắn hơn. Bạn có thể làm cho nó ngắn hơn nữa bằng cách bỏ qua câu lệnh khác for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='').
djhurio

@djhurio - Tôi biết, gần như không bao giờ trường hợp trong R a for loop sẽ giúp được gì cả. Về đề nghị của bạn: Ý tưởng tuyệt vời! Đề xuất này được kết hợp trong câu trả lời.
duckmayr

1
@djhurio - đủ công bằng; Tôi đã quá bận rộn để xem sự khác biệt được giới thiệu bằng cách bỏ qua tuyên bố khác Tôi không thấy bạn đã thay đổi như thế nào ngay từ đầu. Chỉnh sửa ngay. Công việc tuyệt vời
duckmayr

1
@djhurio @duckmayr có một giải pháp 73 byte về cơ bản là sử dụng giải pháp này và sử dụng một cách tiếp cận hơi khác để trích xuất các ký tự. Tôi thực sự không cảm thấy muốn đăng nó như một câu trả lời riêng biệt. Cũng lưu ý rằng ...[[1]]dài hơn el(...)nhưng ngắn hơn unlist(...), với điều kiện ...là danh sách có độ dài 1.
Giuseppe

1
xước đó, tôi tìm thấy một câu trả lời 70 tạm biệt kể từ khi 0nulnhân vật và được chuyển đổi sang các chuỗi rỗng.
Giuseppe

2

MATL , 6 byte

vi"@X~

Không hoạt động trong môi trường TIO, nhưng hoạt động tốt khi triển khai MATLAB và nhờ một bản vá mới, bạn có thể dùng thử trên MATL Online

X~bằng setxor, hoặc khác biệt đối xứng, thực hiện chính xác những gì thách thức yêu cầu. Phần còn lại chỉ là lặp qua đầu vào i"@và bắt đầu bằng một chuỗi trống bằng cách nối toàn bộ ngăn xếp trống khi bắt đầu (cảm ơn Luis Mendo).


2

Python 2 , 56 byte

-2 byte nhờ xnor. -3 byte nhờ vào các lò nướng.

lambda s:reduce(lambda a,c:a.replace(c,'')+c[c in a:],s)

Hãy thử trực tuyến!

Nghĩa đen chỉ là đánh golf giả. : P


1
Lưu 2 byte : s=(s+c).replace(c,c[c in s:]).
xnor

@xnor Đó là một số môn đánh gôn cơ bản được thực hiện rất thông minh. Cảm ơn!
hoàn toàn là

1
-1 byte :s=s.replace(c,'')+c[c in s:]
ovs


1

JavaScript (ES6), 60 byte

s=>[...s].map(c=>s=s.match(c)?s.split(c).join``:s+c,s='')&&s

Các trường hợp thử nghiệm


Tôi đã chuyển câu trả lời Retina của @ MartinEnder và nó chỉ có 45 byte ...
Neil


1

APL + THẮNG, 19 byte

Logic tương tự như giải pháp J của Galen.

(2|+⌿⌽<\⌽c∘.=c)/c←⎕     

1

Ngôn ngữ Wolfram (Mathicala) , 36 byte

#//.{a___,x_,b___,x_,c___}:>{a,b,c}&

Hãy thử trực tuyến!

Lấy đầu vào và đầu ra dưới dạng một danh sách các ký tự.

Làm thế nào nó hoạt động

Sử dụng //.(bí danh ReplaceRepeated) để tìm hai ký tự lặp lại và xóa cả hai, cho đến khi không còn ký tự lặp lại. Nếu nhân vật xảy ra nhiều hơn hai lần, Mathicala sẽ luôn xóa hai lần xuất hiện đầu tiên. Vì vậy, nếu một nhân vật xuất hiện một số lần lẻ, trường hợp cuối cùng của nó sẽ luôn là lần tồn tại.


1

Prolog 81 byte

a([],O,O).
a([I|J],K,O):-delete(K,I,F),(K=F->append(K,[I],M),a(J,M,O);a(J,F,O)).

Phiên bản không bị xáo trộn:

append_and_eraze([], Output, Output).
append_and_eraze([I | Input], Interim, Output) :-
    delete(Interim, I, Filtered),
    ( Interim = Filtered ->
      append(Interim, [I], Interim1),
      append_and_eraze(Input, Interim1, Output)
    ;
    append_and_eraze(Input, Filtered, Output)
    ).
  1. delete/3 đảm bảo rằng đối số thứ ba của nó thống nhất với đối số thứ nhất, với tất cả các phiên bản của đối số thứ hai được loại bỏ khỏi đối số đó.
  2. Nếu những cái đó giống nhau, chúng ta sẽ thêm phần tử (nó không bị xóa).
  3. append/3 như tên của nó, nối thêm một yếu tố vào danh sách.
  4. Chúng tôi lặp lại các yếu tố của đầu vào cho đến khi chúng tôi đạt [](danh sách trống), tại thời điểm đó, kết quả trung gian sẽ thống nhất với kết quả mong muốn.

Kiểm tra:

?- append_and_eraze(`ABCDBCCBE`, [], X), string_codes(Y, X).
X = [65, 68, 67, 66, 69],
Y = "ADCBE".

?- append_and_eraze(`ABCXYZCABXAYZ`, [], X), string_codes(Y, X).
X = [65],
Y = "A".

?- append_and_eraze(`aAABBbAbbB`, [], X), string_codes(Y, X).
X = [97, 65, 98, 66],
Y = "aAbB".

?- append_and_eraze(`GG`, [], X), string_codes(Y, X).
X = [],
Y = "".

Một số Prolog coi các chuỗi trong dấu ngoặc kép là danh sách, SWI có thể được cấu hình để làm tương tự, nhưng để đơn giản, tôi đã sử dụng string_codes/2để định dạng đầu ra độc đáo.



1

R , 84 byte

y=el(strsplit(scan(,""),""));cat(unique(y[colSums(outer(y,y,"=="))%%2>0],,T),sep="")

Hãy thử trực tuyến!

Một giải pháp khác, nhưng có câu trả lời R tốt hơn ở đây.

R , 88 byte

z=table(y<-el(strsplit(scan(,""),"")));cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="")

Hãy thử trực tuyến!

Cảm ơn Giuseppe cho -7 byte!

Có một câu trả lời ngắn hơn bởi duckmayr .

  1. scan(,"") đọc đầu vào từ stdin.
  2. y<-el(strsplit(scan(,""),""))phân chia đầu vào theo các ký tự và lưu dưới dạng y.
  3. z=table(y<-el(strsplit(scan(,""),"")))tính tần số của từng ký tự và lưu bảng kết quả như z;
  4. unique(y,,T) lấy các ký tự độc đáo từ phía bên phải.
  5. names(z[!z%%2]) chỉ chọn số lượng và trích xuất tên.
  6. setdiff(unique(y,,T),names(z[!z%%2])) xóa các ký tự có số chẵn
  7. cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="") in đầu ra.

Lý do cho lỗi của bạn là el()do methodsgói, mặc dù thường được tải theo mặc định, không phải do TIO (được thảo luận trong câu trả lời của tôi bên dưới)
duckmayr

lý do tại sao bạn đang sử dụng rev(unique(rev(y)))? Sẽ không unique(y)làm việc chứ? ooohhh chờ tôi thấy, bạn muốn các nhân vật độc đáo từ phải sang trái. Trong trường hợp đó unique(y,,T)(cài đặt fromLast=T) sẽ là 88 byte .
Giuseppe




0

Ruby , 53 byte

->s{s.reverse.uniq.select{|c|s.count(c)%2>0}.reverse}

Hãy thử trực tuyến!

Đầu vào và đầu ra đều là một mảng ký tự. Kiểm tra các cuộc gọi mã .chars.joinđể thuận tiện.

Giải trình

Sử dụng thực tế là các chữ cái trong chuỗi kết quả xuất hiện một số lần lẻ và theo thứ tự từ phải sang trái.

->s{                # lambda function taking char-array argument
    s.reverse           # reverse the input
    .uniq               # get unique characters
    .select{|c|         # select only those which...
        s.count(c)%2>0      # appear in the input array an odd number of times
    }.reverse           # reverse back and return
}

0

Bình thường, 13 byte

{_xD_Qf%/QT2Q

Lấy đầu vào là danh sách các ký tự. Kiểm tra nó ra!

      f     Q            (f)ilter input (Q)
        /QT              On how many times (/) each character (T) appears in the 
                           input (Q)
       %   2             Only allow odd numbers of occurences (when x % 2 = 1)
 _xD_Q                   Sort (D) descending (the first _) by the location (x) of 
                           the last (the second _) inde(x) of the target character
                           in the input (Q)
{                        Remove duplicates

0

Röda , 34 byte

{a=[]a-=_ if[_1 in a]else a+=_1;a}

Hãy thử trực tuyến!

Đây là một bản dịch trực tiếp của mã giả. Nó coi đầu vào và đầu ra là luồng ký tự.

Giải trình:

{                    /* Anonymous function                   */
    a=[]             /* initialize a                         */
                     /* For each character _1 in the stream: */
    a-=_ if[_1 in a] /*  Remove it from a if a contains it   */
    else a+=_1;      /*  Otherwise append it to a            */
    a                /* Push characters in a to the stream   */
}

0

Con trăn 3 , 73 byte

Không phải là ngắn nhất, nhưng tôi thích cách tiếp cận này.

lambda s:''.join(c*(s.count(c)%2)*(i==s.rfind(c))for i,c in enumerate(s))

Hãy thử trực tuyến!

Vòng lặp thông qua chuỗi, chỉ giữ lại các ký tự trong đó:

  • (s.count(c)%2) == 0 - Nhân vật xuất hiện một số lần chẵn.
  • (i==s.rfind(c)) - Chỉ số hiện tại là sự xuất hiện cuối cùng của nhân vật trong câu hỏi.

0

REXX , 102 byte

a=arg(1)
s=''
do while a>''
  b=right(a,1)
  if countstr(b,a)//2 then s=b||s
  a=changestr(b,a,'')
  end
say s

Hãy thử trực tuyến!

Cách thức hoạt động: Lấy chữ cái ngoài cùng bên phải, xem số lần xuất hiện là chẵn hay lẻ (cũng tăng gấp đôi như một giá trị thật) và nếu lẻ, hãy thêm nó vào chuỗi đầu ra. Sau đó loại bỏ tất cả các lần xuất hiện của chữ cái từ chuỗi đầu vào. Lặp lại cho đến khi đầu vào cạn kiệt.



0

Java 8, 93 byte

Một lambda từ Stringđến String. Chỉ cần thực hiện mã giả trong câu hỏi.

s->{String o="";for(char c:s.toCharArray())o=o.indexOf(c)<0?o+c:o.replace(c+"","");return o;}

Dùng thử trực tuyến

Java 8, 182 byte

Đây là một lambda khác cùng loại sử dụng luồng! Nó có thể hiệu quả hơn.

s->s.join("",s.chars().mapToObj(c->(char)c+"").filter(c->s.replaceAll("[^"+c+"]","").length()%2>0).distinct().sorted((c,d)->s.lastIndexOf(c)-s.lastIndexOf(d)).toArray(String[]::new))

Dùng thử trực tuyến

Ung dung

s ->
    s.join(
        "",
        s.chars()
            .mapToObj(c -> (char) c + "")
            .filter(c -> s.replaceAll("[^" + c + "]", "").length() % 2 < 0)
            .distinct()
            .sorted((c, d) -> s.lastIndexOf(c) - s.lastIndexOf(d))
            .toArray(String[]::new)
    )

0

R , 70 byte

function(s){for(i in utf8ToInt(s))F=c(F[F!=i],i*!i%in%F);intToUtf8(F)}

Hãy thử trực tuyến!

Tôi đã được djhurio khuyến khích đăng giải pháp này; câu trả lời của djhurio có thể được tìm thấy ở đây .

Điều này sử dụng ý tưởng tương tự như câu trả lời của duckmayr , nhưng nó thúc đẩy cách tiếp cận số bằng cách chuyển đổi chuỗi thành mã của nó thay vì tách nó thành các ký tự và là một chức năng chứ không phải là một chương trình đầy đủ để nó có thể trả về chuỗi mới thay vì in ra thiết bị xuất chuẩn .

function(s) {
 for(i in utf8ToInt(s))           # convert string to codepoints and iterate over it
  F=c(F[F!=i],                    # remove duplicates and append
      i*!i%in%F)                  # 0 if in F, i otherwise
 intToUtf8(F)                     # collapse from codepoints to string
}

Một quan sát quan trọng là Fđược khởi tạo thành FALSEhoặc 0utf8ToInt(0)=="", do đó, điều này sẽ thành công cho chuỗi trống cũng như thu gọn chính xác các điểm mã.


0

PHP, 71 + 1 byte

while(~$c=$argn[$i++])$s=strstr($s,$c)?strtr($s,[$c=>""]):$s.$c;echo$s;

Chạy như ống với -nRhoặc thử trực tuyến .



0

SNOBOL4 (CSNOBOL4) , 97 95 byte

	S =INPUT
N	S LEN(1) . C REM . S :F(O)
	O C :S(R)
	O =O C :(N)
R	O C =:S(R)F(N)
O	OUTPUT =O
END

Hãy thử trực tuyến!

	S =INPUT			;* read input
N	S LEN(1) . C REM . S :F(O)	;* take the first character of S and assign it to C,
					;* assign the remainder to S, and if S has no characters left, goto O
	O C :S(R)			;* if C matches anything in O, goto R, otherwise go to next line
	O =O C :(N)			;* append C to O and goto N
R	O C =:S(R)F(N)			;* as long as C matches O, replace it with ''
					;* (unassigned variables default to the null string)
					;* then goto N once it fails to match
O	OUTPUT =O			;* output the string
END					;* terminate the program
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.