Ekleme ve silme


14

Yalnızca harflerden oluşan bir satır verildiğinde aşağıdaki işlemleri gerçekleştirin:

  • Başlangıçta boş bir dize tutarsınız.
  • Dizede bir sonraki giriş karakteri varsa, dizeden çıkarın.
  • Bir sonraki giriş karakteri dizede değilse, dizeye ekleyin.

Dizenin son durumunu çıktılar.

Girişin en az bir karakter içerdiğini (yani boş olmayan) güvenli bir şekilde kabul edebilirsiniz, ancak çıktının boş olmadığının garantisi yoktur.

Pseudocode (Bunu golf oynamaktan çekinmeyin):

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

Giriş, normal ifadeyle eşleşir ^[A-Za-z]+$.

Örnek test senaryoları:

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

Giriş uygulanabilir herhangi bir şekilde verilebilir, ancak çıktı için bir dize olarak ve aynı şekilde ele alınmalıdır. Program gerektiğini değil bir hata ile çıkın.

Her dilde en kısa program kazanır!

Ekstra (İsteğe bağlı): Lütfen programınızın nasıl çalıştığını açıklayın. Teşekkür ederim.


Hat boş olabilir mi?
user202729

1
@ user202729 Hayır. Biraz değiştirdim (herhangi bir cevabı geçersiz kılmıyor), böylece giriş asla boş kalmayacak.
iBug

1
Öyleyse neden ais523'ün düzenleme önerisini (bağlantı) reddettik ?
user202729

Yanıtlar:


10

Haskell , 44 42 bayt

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

Çevrimiçi deneyin! Düzenleme: Zgarb sayesinde -2 bayt!

Açıklama:

İkinci satır, bir (#)dize sve bir karakter alan xve kaldırma veya ekleme işlemini gerçekleştiren bir işlevi tanımlar . Bu elde edilir filterher geçtiği dışarı ing xin sdizisi ile sonuçlanır z. Eğer xoluşmaz s, daha sonra zeşittir sve z++[x|z==s]özgün dizeyi verir xeklenir. Aksi takdirde [x|z==s]boş dize verir ve yalnızca filtrelenmiş dize döndürülür.

foldl(#)"", dizeyi ""alan ve işlevle birlikte ilk boş dizeyi bir karakter ekleyen anonim bir işlevdir (#).


2
Filtreyi yeniden kullanarak 42 bayt .
Zgarb


8

J , 21 19 bayt

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

Nasıl çalışır:

=/~ - dizedeki karakterlerin eşitlik tablosunu oluşturur:

   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#. - her satırın taban 1 dönüşümüne göre toplamı (harfin kaç kez oluştuğu)

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

~:&.|- tersine çevirin, sonra yumru elek uygulayın (benzersiz karakterdir) ve tekrar ters çevirin. Böylece karakter dizisinin son tekrarlarını buluyorum:

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

* - sring'deki karakterin son konumu için sayıyı 1 ile çarpar, aksi takdirde yukarıdakilerle hesaplanır. ~:&.|

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

2| - modulo 2 (eşit olan karakterlerin konumlarını 0 olarak ayarlar):

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

#~- sağ argüman sol argümanını kopyalayın. kere (~ argümanların yerlerini değiştirir)

]f # a A

Çevrimiçi deneyin!


6

Brainfuck, 95 bayt

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

Çevrimiçi Deneyin

Nasıl çalışır

, 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 bayt

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

Çevrimiçi deneyin!

Djhurio sayesinde -15 bayt

açıklama

djhurio bir fordöngüden kaçınarak mükemmel bir R yanıtı sağladı - R programcıları içgüdüsel olarak kural olarak (kendim dahil). İşte bir fordöngü kullanan (ve işlemde birkaç bayt kaydeden) bir R cevabı .

  • x=scan(,''); - girdiyi değişkene atama x
  • y=''; - adlı bir değişkente boş bir dize oluşturun y
  • for(i in el(strsplit(x,'')))- her karakter iiçinx
  • y=c(y[y!=i],if(!i%in%y)i)- atamak yher eleman yeşit değildir iekleme, ieğer izaten değildiy
  • cat(y,sep='')- yaralarında boşluk kalmadan öğelerini yazdırın

Not

Yukarıdaki TIO bağlantısını tıklarsanız, başlıkta bulabilirsiniz library(methods); Bu, djhurio'nun işlevle ilgili olarak yaşadığı hatayı ele almaktırel() - işlev, methodskullandığım R'nin herhangi bir sürümünde varsayılan olarak yüklenen paket tarafından sağlanır , ancak herhangi bir nedenle TIO tarafından yüklenmez. Eğer library(methods)başlıktan çıkarılır ve unlistonun yerine kullanılırsa el, dört bayt kazanırım , ancak djhurio da sırasıyla 96 88 ve 99'a bayt sayımlarımızı koyar .


Güzel. Döngü için asla düşünülmez daha kısa olacaktır. Başka bir ifadeyi atlayarak bunu daha da kısaltabilirsiniz for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='').
djhurio

@djhurio - Biliyorum, Ra'da döngü için herhangi bir şeye yardımcı olacağı neredeyse hiç olmuyor. Önerinizle ilgili: Harika fikir! Öneri şimdi cevaba eklenmiştir.
duckmayr

1
@djhurio - yeterince adil; Başka bir ifadenin atladığı farka bakmakla çok meşguldüm, başlangıcını nasıl değiştirdiğini görmedim. Şimdi düzenleniyor. Harika iş!
duckmayr

1
@djhurio @duckmayr Bu çözümü alan ve karakterleri ayıklamak için biraz farklı bir yaklaşım kullanan 73 baytlık bir çözüm var. Bunu ayrı bir cevap olarak göndermek istemiyordum. Ayrıca , uzunluk 1'in bir listesi olması şartıyla ...[[1]], daha uzun el(...)ama daha kısa olduğunu unutmayın .unlist(...)...
Giuseppe

1
boşver, ben buldum 70 güle cevap beri 0olduğu nulkarakter ve boş dize dönüştürülür alır.
Giuseppe

2

MATL , 6 bayt

vi"@X~

TIO ortamında çalışmaz, ancak MATLAB uygulamasında iyi çalışır ve yeni bir yama sayesinde MATL Online'da deneyebilirsiniz

X~eşittir setxorya da meydan okumanın tam olarak ne istediğini simetrik fark. Gerisi sadece giriş üzerinde döngü i"@ve başlangıçta boş olan tüm yığını birleştirerek boş bir dize ile başlıyor (teşekkürler Luis Mendo).



1

JavaScript (ES6), 60 bayt

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

Test senaryoları


@ MartinEnder'in Retina cevabını taşıdım ve sadece 45 bayttı ...
Neil


1

APL + WIN, 19 bayt

Galen'in J çözümüne benzer bir mantık.

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

1

Wolfram Dili (Mathematica) , 36 bayt

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

Çevrimiçi deneyin!

Girdi ve çıktıları bir karakter listesi olarak alır.

Nasıl çalışır

Tekrarlanan iki karakter bulunana kadar iki tekrarlanan karakter bulmak ve her ikisini silmek için //.(takma ad ReplaceRepeated) kullanır . Karakter iki defadan fazla ortaya çıkarsa, Mathematica her zaman ilk iki örneği siler. Eğer bir karakter garip sayıda ortaya çıkarsa, son örneği her zaman hayatta kalacaktır.


1

Prolog 81 bayt

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

Gizlenmeyen sürüm:

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 üçüncü argümanının ilk argüman ile birleşmesini ve ikinci argümanın tüm örnekleri ondan kaldırılmasını sağlar.
  2. Bunlar aynı olduğu ortaya çıkarsa, öğeyi ekleriz (kaldırılmadı).
  3. append/3 ismine göre listeye bir eleman ekler.
  4. Ara öğenin []istenen sonuçla birleşeceği noktaya (boş liste) çarpana kadar girişin öğelerini tekrarlıyoruz .

Ölçek:

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

Bazı Prologlar dizeleri çift tırnak içinde listeler olarak ele alır, SWI da aynı şekilde yapılandırılabilir, ancak basitlik açısından string_codes/2çıktıyı güzelce biçimlendirirdim.



1

R , 84 bayt

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

Çevrimiçi deneyin!

Başka bir çözüm, ama burada daha iyi R cevapları var.

R , 88 bayt

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

Çevrimiçi deneyin!

-7 bayt için Giuseppe teşekkürler!

Duckmayr'ın daha kısa bir cevabı var .

  1. scan(,"") stdin'den girişi oku.
  2. y<-el(strsplit(scan(,""),""))girişi karakterlere göre ayırın ve farklı kaydedin y.
  3. z=table(y<-el(strsplit(scan(,""),"")))her karakterin frekanslarını hesaplar ve elde edilen tabloyu z;
  4. unique(y,,T) benzersiz karakterleri sağ taraftan alır.
  5. names(z[!z%%2]) yalnızca çift sayıları seçin ve adları çıkarın.
  6. setdiff(unique(y,,T),names(z[!z%%2])) eşit sayıdaki karakterleri kaldırın.
  7. cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="") çıktıyı yazdırın.

Hatanızla nedeni olduğunu el()gelmektedir methodsgenellikle varsayılan olarak yüklenen ederken, TIO tarafından değil pakette, (aşağıda cevabım tartışılan)
duckmayr

neden kullanıyorsunuz rev(unique(rev(y)))? Sadece unique(y)işe yaramaz mıydı? ooohhh bekle görüyorum, benzersiz karakterleri sağdan sola istiyorsun. Bu durumda unique(y,,T)(ayar fromLast=T) 88 bayt olacaktır .
Giuseppe




0

Yakut , 53 bayt

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

Çevrimiçi deneyin!

Girdi ve çıktının ikisi de karakter dizisidir. Kod çağrılarını test edin .charsve .joinkolaylık sağlayın.

açıklama

Ortaya çıkan dizgideki harflerin tek bir sayı ve sağdan sola doğru sırada görünmesini kullanır.

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

Pyth, 13 bayt

{_xD_Qf%/QT2Q

Girişi karakter listesi olarak alır. Test edin!

      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 bayt

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

Çevrimiçi deneyin!

Bu, sözde kodun doğrudan çevirisidir. Girdi ve çıktıları karakter akışı olarak ele alır.

Açıklama:

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

Python 3 , 73 bayt

En kısa değil, ama bu yaklaşımı seviyorum.

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

Çevrimiçi deneyin!

Dizede dolaşır ve yalnızca şu karakterleri saklar:

  • (s.count(c)%2) == 0 - Karakter eşit sayıda görünür.
  • (i==s.rfind(c)) - Geçerli dizin, söz konusu karakterin son görünümüdür.

0

REXX , 102 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır: En sağdaki mektubu alın, oluşum sayısının çift mi yoksa tek mi (gerçek değer olarak da ikiye katlanır) olup olmadığına bakın ve garip ise, çıktı dizesine ekleyin. Ardından, giriş dizesinden harfin tüm tekrarlarını kaldırın. Giriş bitene kadar tekrarlayın.



0

Java 8, 93 bayt

A lambda Stringiçin String. Sadece sözde sözde kodun bir uygulaması.

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

Çevrimiçi Deneyin

Java 8, 182 bayt

İşte aynı türden akışları kullanan başka bir lambda! Muhtemelen daha verimlidir.

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

Çevrimiçi Deneyin

Ungolfed

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 bayt

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

Çevrimiçi deneyin!

Djhurio tarafından bu çözümü yayınlamaya teşvik edildim; djhurio'nun cevabı burada bulunabilir .

Bu, duckmayr'ın yanıtıyla aynı fikri kullanır , ancak dizeyi karakterlere bölmek yerine kod noktalarına dönüştürerek sayısal bir yaklaşım kullanır ve tam bir program yerine bir işlevdir, böylece stdout'a yazdırmak yerine yeni dizeyi döndürebilir .

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
}

Önemli bir gözlem, veya Fiçin başlatılır ve bu da boş dize için başarılı olur ve kod noktalarını doğru şekilde daraltır.FALSE0utf8ToInt(0)==""


0

PHP, 71 + 1 bayt

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

Pipo ile çalıştırın -nRveya çevrimiçi deneyin .



0

SNOBOL4 (CSNOBOL4) , 97 95 bayt

	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

Çevrimiçi deneyin!

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