Tambahkan dan hapus

14

Diberikan satu baris yang hanya terdiri dari huruf, proses sebagai berikut:

  • Anda mempertahankan string yang kosong di awal.
  • Jika karakter input berikutnya ada di dalam string, hapus dari string.
  • Jika karakter input berikutnya tidak ada dalam string, tambahkan ke string.

Keluarkan status akhir string.

Anda dapat dengan aman menganggap input terdiri setidaknya satu karakter (yaitu tidak kosong), tetapi tidak ada jaminan bahwa output tidak kosong.

Pseudocode (Jangan ragu untuk bermain golf ini):

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

Masukan cocok dengan ekspresi reguler ^[A-Za-z]+$ .

Contoh uji kasus:

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

Input dapat diberikan dengan cara apa pun yang berlaku, tetapi harus diperlakukan sebagai string, dan sama untuk output. Program seharusnya tidak keluar dengan kesalahan.

Program terpendek di setiap bahasa menang!

Ekstra (Opsional): Tolong jelaskan bagaimana program Anda bekerja. Terima kasih.

iBug
sumber
Bisakah salurannya kosong?
user202729
1
@ user202729 Tidak. Saya mengubah sedikit (tidak membatalkan jawaban apa pun) sehingga input tidak pernah kosong.
iBug
1
Jadi mengapa Anda menolak saran sunting (tautan) ais523 ?
user202729

Jawaban:

10

Haskell , 44 42 byte

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

Cobalah online! Sunting: -2 bytes berkat Zgarb!

Penjelasan:

Baris kedua mendefinisikan fungsi (#)yang mengambil string sdan karakter xdan melakukan penghapusan atau penambahan. Ini dicapai dengan filtermemasukkan setiap kejadian xdalam s, menghasilkan string z. Jika xtidak muncul s, maka zsama dengan sdan z++[x|z==s]menghasilkan string asli denganx ditambahkan. Kalau tidak, [x|z==s]menghasilkan string kosong dan hanya string yang difilter dikembalikan.

foldl(#)""adalah fungsi anonim yang mengambil string dan menambahkan satu karakter setelah yang lain string awalnya kosong ""dengan fungsi (#).

Laikoni
sumber
2
42 byte dengan menggunakan kembali filter.
Zgarb
9

Jelly , 3 byte

œ^/

Cobalah online!

Program lengkap.

Erik the Outgolfer
sumber
Kenapa œ^/tidak cukup?
Jonathan Allan
@ JonathanAllan Program tidak boleh keluar dengan kesalahan.
Erik the Outgolfer
the input is never emptyNah, sekarang sudah berfungsi.
user202729
8

J , 21 19 byte

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

Bagaimana itu bekerja:

=/~ - membuat tabel persamaan karakter dalam string:

   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#. - jumlah setiap baris dengan konversi basis 1 (berapa kali huruf itu muncul)

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

~:&.|- membalikkan, kemudian menerapkan nub saringan (adalah karakter unik) dan membalikkan lagi. Jadi saya menemukan kejadian terakhir dari karakter dalam string:

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

* - mengalikan hitungan dengan 1 untuk posisi terakhir karakter dalam sring, dengan 0 jika tidak, dihitung dengan di atas ~:&.|

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

2| - modulo 2 (set ke 0 posisi karakter yang memiliki jumlah genap):

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

#~- salin argumen kanan ke kiri. kali (~ membalikkan tempat args)

]f # a A

Cobalah online!

Galen Ivanov
sumber
6

Brainfuck, 95 byte

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

Cobalah secara Online

Bagaimana itu bekerja

, 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
Jo King
sumber
4

Haskell , 47 byte

Satu lagi memotong debu berkat Bruce Forte.

import Data.List
foldl1(\x y->union(x\\y)$y\\x)

Cobalah online!

Mengambil daftar String.

Perbedaan simetris menyebalkan ...

benar-benar manusiawi
sumber
++menghemat 2 byte lebih uniondengan metode ini.
Ørjan Johansen
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='')

Cobalah online!

-15 byte berkat djhurio

Penjelasan

djhurio memberikan jawaban R yang sangat baik untuk menghindari forperulangan - seperti yang dilakukan oleh programmer R sebagai aturan (termasuk saya sendiri). Inilah jawaban R yang menggunakan forloop (dan menyimpan beberapa byte dalam proses).

  • x=scan(,''); - tetapkan input ke dalam variabel x
  • y=''; - buat string kosong dalam variabel yang disebut y
  • for(i in el(strsplit(x,'')))- untuk setiap karakter idalamx
  • y=c(y[y!=i],if(!i%in%y)i)- tetapkan ke ysetiap elemen yyang tidak sama dengan i, tambahkan ijika ibelum masuky
  • cat(y,sep='')- cetak elemen ytanpa spasi di antara mereka

Catatan

Jika Anda mengklik tautan TIO di atas, Anda akan menemukannya di tajuk library(methods); ini untuk mengatasi kesalahan yang dialami djhurio mengenai el()fungsi - fungsi ini disediakan oleh methodspaket, yang dalam versi R apa pun yang saya gunakan, dimuat secara default, tetapi untuk alasan apa pun bukan oleh TIO. Jika library(methods)dihapus dari header dan unlistdiganti el, saya memperoleh empat byte, tetapi begitu juga djhurio , menempatkan byte kami masing-masing sebesar 96 88 dan 99.

duckmayr
sumber
Bagus Tidak pernah terpikirkan untuk loop akan lebih pendek. Anda dapat membuatnya lebih pendek dengan menghilangkan pernyataan orang lain for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='').
djhurio
@ Djurio - Saya tahu, hampir tidak pernah terjadi bahwa dalam R a for loop akan membantu dengan apa pun. Mengenai saran Anda: Ide bagus! Saran sekarang dimasukkan dalam jawaban.
duckmayr
1
@djhurio - cukup adil; Saya terlalu sibuk melihat perbedaan yang diperkenalkan dengan menghilangkan pernyataan lain yang saya tidak melihat bagaimana Anda telah mengubah awal. Editing sekarang. Kerja bagus!
duckmayr
1
@djhurio @duckmayr ada solusi 73 byte yang pada dasarnya mengambil solusi ini dan menggunakan pendekatan yang sedikit berbeda untuk mengekstraksi karakter. Saya tidak merasa ingin mempostingnya sebagai jawaban terpisah. Perhatikan juga bahwa ...[[1]]lebih panjang dari el(...)tetapi lebih pendek dari unlist(...), asalkan itu ...adalah daftar panjang 1.
Giuseppe
1
awal itu, saya menemukan jawaban 70 bye karena 0adalahnul karakter dan akan dikonversi menjadi string kosong.
Giuseppe
2

MATL , 6 byte

vi"@X~

Tidak bekerja di lingkungan TIO, tetapi berfungsi dengan baik pada implementasi MATLAB, dan berkat tambalan baru, Anda dapat mencobanya di MATL Online

X~sama setxor, atau perbedaan simetris, yang melakukan apa yang diminta tantangan. Sisanya hanya mengulangi input i"@dan mulai dengan string kosong dengan menyatukan seluruh tumpukan yang kosong di awal (terima kasih Luis Mendo).

Sanchises
sumber
2

Python 2 , 56 byte

-2 byte terima kasih kepada xnor. -3 bytes terima kasih kepada ovs.

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

Cobalah online!

Secara harfiah hanya golf kodesemu. : P

benar-benar manusiawi
sumber
1
Hemat 2 bytes: s=(s+c).replace(c,c[c in s:]).
xnor
@ xnor Itu beberapa golf dasar yang dilakukan dengan sangat cerdik. Terima kasih!
totallyhuman
1
-1 byte :s=s.replace(c,'')+c[c in s:]
ovs
1
56 byte menggunakan pengurangan
ovs
1

JavaScript (ES6), 60 byte

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

Uji kasus

Arnauld
sumber
Saya mengirim jawaban @ MartinEnder pada Retina dan hanya 45 byte ...
Neil
1

q , 38 byte

""{$[y in x;except;,][x;y]}/
skeevey
sumber
1

APL + WIN, 19 byte

Logika mirip dengan solusi J Galen.

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

Bahasa Wolfram (Mathematica) , 36 byte

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

Cobalah online!

Mengambil input dan output sebagai daftar karakter.

Bagaimana itu bekerja

Menggunakan //.(alias ReplaceRepeated) untuk menemukan dua karakter yang diulang dan menghapus keduanya, sampai tidak ada lagi karakter yang diulang. Jika karakter muncul lebih dari dua kali, Mathematica akan selalu menghapus dua kejadian pertama. Jadi, jika sebuah karakter muncul beberapa kali ganjil, contoh terakhirnya akan selalu menjadi yang bertahan.

Misha Lavrov
sumber
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)).

Versi tidak dikaburkan:

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 memastikan bahwa argumen ketiga menyatu dengan argumen pertama, dengan semua contoh argumen kedua dihapus dari itu.
  2. Jika hasilnya ternyata sama, kami menambahkan elemen (itu tidak dihapus).
  3. append/3 sesuai namanya, menambahkan elemen ke daftar.
  4. Kami berulang pada elemen input sampai kami menekan [](daftar kosong), pada titik mana hasil antara akan menyatukan dengan hasil yang diinginkan.

Uji:

?- 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 = "".

Beberapa Prolog memperlakukan string dalam tanda kutip ganda sebagai daftar, SWI dapat dikonfigurasi untuk melakukan hal yang sama, tetapi demi kesederhanaan, saya terbiasa string_codes/2memformat output dengan baik.

wvxvw
sumber
1

Perl 5, 28 + 2 (-pF) = 30 byte

$\=~s/$_//g||($\.=$_)for@F}{

Cobalah online

Nahuel Fouilleul
sumber
1

R , 84 byte

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

Cobalah online!

Solusi lain, tetapi ada jawaban R yang lebih baik di sini.

R , 88 byte

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

Cobalah online!

Terima kasih kepada Giuseppe untuk -7 byte!

Ada jawaban yang lebih pendek dari duckmayr .

  1. scan(,"") baca input dari stdin.
  2. y<-el(strsplit(scan(,""),""))pisahkan input dengan karakter dan simpan sebagai y.
  3. z=table(y<-el(strsplit(scan(,""),"")))menghitung frekuensi masing-masing karakter dan menyimpan tabel yang dihasilkan sebagai z;
  4. unique(y,,T) ambil karakter unik dari sisi kanan.
  5. names(z[!z%%2]) pilih hanya hitungan genap dan ekstrak nama.
  6. setdiff(unique(y,,T),names(z[!z%%2])) hapus karakter dengan jumlah genap.
  7. cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="") cetak hasilnya.
djhurio
sumber
Alasan untuk kesalahan Anda adalah yang el()berasal dari methodspaket, yang walaupun biasanya dimuat secara default, bukan oleh TIO (dibahas dalam jawaban saya di bawah ini)
duckmayr
mengapa Anda menggunakan rev(unique(rev(y)))? Tidak hanya unique(y)bekerja? ooohhh tunggu, saya mengerti, Anda ingin karakter unik dari kanan ke kiri. Dalam hal ini unique(y,,T)(pengaturan fromLast=T) akan menjadi 88 byte .
Giuseppe
0

Alice , 9 byte

/X&@
\io/

Cobalah online!

Penjelasan

Pada dasarnya port jawaban Erik . Terlepas dari sedikit pengalihan IP, kodenya benar-benar hanya:

i&Xo@

yang tidak:

i   Read all input.
&X  Fold symmetric multiset difference over the input.
o   Output the result.
@   Terminate.
Martin Ender
sumber
0

APL (Dyalog) , 16 byte

{(,⍨~∩)/⍣(≢⍵)⊖⍵}

Cobalah online!

Jika kesalahan dibolehkan, ini akan menjadi 9 byte:

(,⍨~∩)/∘⊖
Erik the Outgolfer
sumber
Apa yang Anda maksud dengan kesalahan?
FrownyFrog
@FrownyFrog Versi 9-byte akan melempar DOMAIN ERRORjika string kosong, karena (,⍨~∩)tidak memiliki elemen identitas yang telah ditentukan.
Erik the Outgolfer
0

Ruby , 53 byte

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

Cobalah online!

Input dan output keduanya adalah array karakter. Tes panggilan kode .charsdan.join untuk kenyamanan.

Penjelasan

Menggunakan fakta bahwa huruf-huruf dalam string yang dihasilkan muncul beberapa kali dan dalam urutan dari kanan ke kiri.

->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
}
Justin Mariner
sumber
0

Pyth, 13 byte

{_xD_Qf%/QT2Q

Dimasukkan dalam input sebagai daftar karakter. Uji itu!

      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
Steven H.
sumber
0

Rosda , 34 byte

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

Cobalah online!

Ini adalah terjemahan langsung dari pseudocode. Ini memperlakukan input dan output sebagai aliran karakter.

Penjelasan:

{                    /* 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   */
}
fergusq
sumber
0

Python 3 , 73 byte

Bukan yang terpendek, tapi saya suka pendekatan ini.

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

Cobalah online!

Lewati string, simpan hanya karakter-karakter itu di tempat:

  • (s.count(c)%2) == 0 - Karakter muncul beberapa kali.
  • (i==s.rfind(c)) - Indeks saat ini adalah penampilan terakhir dari karakter yang dimaksud.
FlipTack
sumber
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

Cobalah online!

Cara kerjanya: Ambil huruf paling kanan, lihat apakah jumlah kemunculannya genap atau ganjil (yang juga berfungsi ganda sebagai nilai kebenaran) dan jika ganjil, tambahkan ke string output. Kemudian hapus semua kemunculan huruf dari string input. Ulangi sampai input habis.

idrougge
sumber
0

Java 8, 93 byte

Seekor lambda dari Stringke String. Hanya implementasi kodesemu dalam pertanyaan.

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

Cobalah secara Online

Java 8, 182 byte

Inilah lambda lain dari jenis yang sama yang menggunakan stream! Mungkin lebih efisien.

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

Cobalah secara Online

Tidak disatukan

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)
    )
Jakob
sumber
0

R , 70 byte

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

Cobalah online!

Saya didorong oleh djhurio untuk mengirim solusi ini; Jawaban djhurio dapat ditemukan di sini .

Ini menggunakan ide yang sama dengan jawaban duckmayr , tetapi memanfaatkan pendekatan numerik dengan mengubah string ke codepoint-nya daripada membaginya menjadi karakter, dan merupakan fungsi daripada program penuh sehingga dapat mengembalikan string baru daripada mencetak ke stdout .

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
}

Satu pengamatan penting adalah itu F diinisialisasi ke FALSEatau 0dan utf8ToInt(0)=="", jadi ini akan berhasil untuk string kosong serta dengan benar menciutkan codepoints.

Giuseppe
sumber
0

PHP, 71 +1 byte

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

Jalankan sebagai pipa dengan -nRatau coba online .

Titus
sumber
0

Python 3.6 , 69 byte

lambda a:"".join({c:1 for c in a[::-1] if a.count(c)%2}.keys())[::-1]

Cobalah online!

Urutan penyisipan Dict dipertahankan dalam Python 3.6.

pengguna285259
sumber
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

Cobalah online!

	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
Giuseppe
sumber