pwaS eht tirsf dna tasl setterl için hace dorw


30

Veya, "Her kelimenin ilk ve son harflerini değiştir"

Zorluğunuz, bir sınırlayıcı olarak kullanılacak (her bir kelimeyi ayırmak için) bir alfabetik ASCII karakter dizisinin yanı sıra bir karakter olarak verilen her kelimenin ilk ve son harflerini değiştirmek. Tek karakterli bir kelime varsa, onu rahat bırak.

Örnekler / test senaryoları, küçük harfler ve ayırıcı olarak boşluk kullanırlar.

Noktalama işaretlerini kullanmanıza gerek yoktur; girişlerin tümü sadece bir sınırlayıcı ile ayrılmış, tek tip bir kasanın tamamı a'dan z'ye kadar olan harflerden oluşacaktır.

Örneğin, "merhaba dünya" dizesiyle:

Input string: "hello world"
Identify each word: "[hello] [world]"
Identify the first and last letters of each word: "[[h]ell[o]] [[w]orl[d]]"
Swap the first letters of each word: "[[o]ell[h]] [[d]orl[w]]"
Final string: "oellh dorlw"

NOT: Sınırlayıcının ayrı bir şekilde girilmesine gerek yoktur. Sınırlayıcı sadece kelimeleri ayırmak için kullanılan karakterdir. Her şey olabilir. Yaratıcı golf oyuncuları için seçenekleri açık bırakmak istedim, bu yüzden sadece boşluklarla veya yeni çizgilerle sınırlamak istemedim. Sınırlayıcı, yalnızca giriş dizesindeki sözcükleri ayıran bir karakterdir.

Test durumları:

"swap the first and last letters of each word" -> "pwas eht tirsf dna tasl setterl fo hace dorw"
"hello world" -> "oellh dorlw"
"test cases" -> "test sasec"
"programming puzzles and code golf" -> "grogramminp suzzlep dna eodc folg"
"in a green meadow" -> "ni a nreeg weadom"
"yay racecar" -> "yay racecar"

3
Noktalama işaretleri nasıl tedavi edilmelidir? Hello, world!olur ,elloH !orldw(noktalama işaretini bir harf olarak değiştirmek) veya oellH, dorlw!(noktalama işaretini yerinde tutmak)?
Phelype Oleinik

3
@PhelypeOleinik Noktalama işaretlerini kullanmanıza gerek yoktur; tüm girdiler yalnızca a'dan z'ye harflerden ve tek biçimli bir durumdan oluşacaktır.
Yoldaş SparklePony

4
İkinci paragraf , sınırlayıcı olarak kullanılacak bir karakterin yanı sıra dördüncü boşluklarla ayrılmış olarak okur . Hangisi o?
Adam

@ Adám Herhangi bir alfabetik olmayan karakter. Netleştirmek için düzenleyeceğim.
Yoldaş SparklePony

1
@ BenjaminUrquhart Evet. İsterseniz girişi bir işlev argümanı olarak alabilirsiniz.
Yoldaş SparklePony

Yanıtlar:


59

TeX, 216 bayt (4 satır, her biri 54 karakter)

Bayt sayısıyla ilgili olmadığı için, dizgi çıktısının kalitesi ile ilgilidir :-)

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

Çevrimiçi Deneyin! (Overleaf; nasıl çalıştığından emin değilim)

Tam test dosyası:

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

\S{swap the a first and last letters of each word}

pwas eht a tirsf dna tasl setterl fo hace dorw

\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}

\bye

Çıktı:

enter image description here


LaTeX için sadece kazan plakasına ihtiyacınız var:

\documentclass{article}
\begin{document}

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

\S{swap the a first and last letters of each word}

pwas eht a tirsf dna tasl setterl fo hace dorw

\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}

\end{document}

açıklama

TeX garip bir canavardır. Normal kodları okumak ve anlamak kendi başına bir başarıdır. Karışık TeX kodunu anlamak birkaç adım daha ileriye gider. Bunu TeX'i de bilmeyen insanlar için anlaşılabilir hale getirmeye çalışacağım, bu yüzden başlamadan önce TeX ile ilgili işleri takip etmeyi kolaylaştıran birkaç kavram:

(Öyle değil) mutlak TeX yeni başlayanlar için

  • İlk olarak, ve bu listede en önemli parça: Kod yok değil , dikdörtgen şeklinde olmak zorunda olsa bile pop kültürü götürebilir öyle düşünmek .

  • TeX bir makro genişleme dilidir. Örnek olarak, TeX'in yazdırılmasını sağlamak için tanımlayabilir \def\sayhello#1{Hello, #1!}ve yazabilirsiniz . Buna “sınırsız makro” denir ve onu ilk (ve sadece bu durumda) parametresiyle beslemek için onu parantez içine alırsınız. Makro argümanı kaptığında TeX bu parantezleri kaldırır. 9 parametreye kadar kullanabilirsiniz: o zaman .\sayhello{Code Golfists}Hello, Code Golfists!\def\say#1#2{#1, #2!}\say{Good news}{everyone}

  • Undelimited makro muadili, tahmin edileceği üzere, olanları sınırlandırılır :) Bir önceki tanım biraz daha yapabiliriz anlamsal : \def\say #1 to #2.{#1, #2!}. Bu durumda, parametreleri parametre metni olarak adlandırılır . Bu tür parametre metni, makro argümanını #1sınırlandırır ( ␣to␣boşluklarla #2ayrılmış ve sınırlandırılan .). Bu tanımdan sonra \say Good news to everyone.genişleyeceğiniz yazı yazabilirsiniz Good news, everyone!. Güzel değil mi? :) Bununla birlikte, sınırlandırılmış bir argüman ( TeXbook'tan alıntı yaparak ) “ {...}girdi içinde parametre olmayan bu belirteçlerin listesi tarafından takip edilen düzgün şekilde iç içe geçmiş gruplara sahip belirteçlerin en kısa (muhtemelen boş) sırası” dır . Bu genişlemesi anlamına gelir\say Let's go to the mall to Martingarip bir cümle üretecek. Bu durumda siz “postu” ilk gerekiyordu ␣to␣ile {...}: \say {Let's go to the mall} to Martin.

  • Çok uzak çok iyi. Şimdi işler garipleşmeye başladı. TeX bir karakter okuduğunda (bir “karakter kodu” ile tanımlanır), o karaktere ne anlama geleceğini tanımlayan bir karaktere “kategori kodu” (catcode, arkadaşlar için :) atar. Bu karakter ve kategori kodu kombinasyonu bir belirteç yapar ( örneğin , burada daha fazlası ). Bizim için burada ilgilenenler temelde:

    • Bir kontrol sekansı (bir makro için lüks bir isim) oluşturabilen jetonları tanımlayan catcode 11 . Varsayılan olarak tüm harfler [a-zA-Z] catcode 11'dir, dolayısıyla \hellotek bir kontrol dizisi olan yazabilirim , \he11okontrol dizisini \heiki karakter 1takip eder, ardından harf izler o, çünkü 1catcode 11 değildir. yaptığı \catcode`1=11bu noktadan sonra, \he11obir kontrol dizisi olacaktır. Önemli bir nokta catcodes TeX ilk elden karakterini gördüğünde ayarlanır ve bu tür catcode olduğunu olmasıdır donmuş ... SONSUZA DEK! (şartlar ve koşullar geçerli olabilir)

    • 0"!@*(?,.-+/ve benzeri diğer karakterlerin çoğu olan catcode 12 . Sadece kağıda yazı yazmak için kullandıkları en az özel tipte kodlardır. Ama hey, kim TeX'i yazmak için kullanıyor? (yine şartlar ve koşullar geçerli olabilir)

    • cehennem olan catcode 13 , :) Gerçekten. Okumayı bırak ve git hayatından bir şeyler yap. Catcode 13'ün ne olduğunu bilmek istemezsin. Hiç 13, Cuma duydum mu? İsmini nereden aldığını tahmin et! Devam etmek kendi sorumluluğunuzdadır! “Aktif” bir karakter olarak da adlandırılan bir kod 13 karakter artık sadece bir karakter değil, aynı zamanda bir makro! Parametrelere sahip olduğunu ve yukarıda gördüğümüz gibi genişleyeceğini tanımlayabilirsiniz. Bunu yaptıktan sonra \catcode`e=13sen düşünmek yapabileceğiniz \def e{I am the letter e!}ANCAK. SEN. YAPAMAM! eartık bir mektup değil, o yüzden biliyorsun \defdeğil \def, öyle \d e f! Oh, söylediğin başka bir mektup mu seçtin? Tamam! \catcode`R=13 \def R{I am an ARRR!}. Çok iyi, Jimmy, dene! Bunu yapmaya ve Rkodunu girmeye cesaret edeceğim ! 13 kodlu kod budur. SAKİNİM! Hadi devam edelim.

  • Tamam, şimdi gruplaşmaya. Bu oldukça basittir. Bir grupta yapılan her ödev ( \defbir ödev işlemidir \let(içine gireceğiz) başka bir oyundur), bir grupta yapılanlar, bu ödev genel olmadığı sürece, söz konusu grubun başlamasından önceki haline geri yüklenir. Grupları başlatmanın birkaç yolu vardır, bunlardan biri 1 ve 2 karakterli kodludur (oh, tekrar kod kodlu). Varsayılan {olarak catcode 1 veya başlangıç ​​grubu ve }catcode 2 veya son gruptur. Bir örnek: \def\a{1} \a{\def\a{2} \a} \aBu yazdırır 1 2 1. Dış grup \aoldu 1o üzere yeniden tanımlandı sonra içeride, 2ve grup bittiğinde, bu iade edildi 1.

  • \letOperasyon başka atama gibi operasyon \def, daha çok farklı. İle \defsen tanımlamak ile şeyler genişleyecektir makrolar \letzaten var olan şeylerin kopyalarını oluşturmak. Sonra \let\blub=\def( =isteğe bağlıdır), eörneğin başlangıcını yukarıdaki catcode 13 öğesinden değiştirebilir \blub e{...ve bununla eğlenebilirsiniz. Ya da daha yerine yapabilirsiniz şeyler kırma düzeltmek (şuna bakar ederim!) RÖrnek: \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Hızlı soru: adını değiştirebilir misiniz \newR?

  • Sonunda, sözde "sahte alanlar". Bu biraz tabu bir konudur, çünkü TeX - LaTeX Yığın Borsasında kazanılan ünün “sahte alan” sorularına cevap vererek kazandığı şöhretin göz ardı edilmemesi gerektiğini iddia ederken, diğerleri gönülden katılmıyorum. Kime katılıyorsun? Bahislerinizi yerleştirin! Bu arada: TeX satır sonunu bir boşluk olarak anlıyor. Aralarında bir satır sonu ( boş bir satır değil) bulunan birkaç sözcük yazmaya çalışın . Şimdi %bu satırların sonuna bir tane ekleyin . Bu satır sonu alanlarını "yorumluyor" gibisin. Bu kadar :)

(Sırala) kodu çözme

Bu dikdörtgeni (tartışmalı) takip etmesi daha kolay bir şey haline getirelim:

{
\let~\catcode
~`A13
\defA#1{~`#113\gdef}
AGG#1{~`#113\global\let}
GFF\else
GHH\fi
AQQ{Q}
AII{\ifxQ}
AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
ADD#1#2#3|{I#2FE{#1}#2#3|H}
ACC#1#2|{D{}#2Q|#1 }
ABBH#1 {HI#1FC#1|BH}
\gdef\S#1{\iftrueBH#1 Q }
}

Her adımın açıklaması

Her satır bir tek komut içerir. Tek tek gidelim, onları parçalara ayırarak:

{
İlk önce bazı değişiklikleri (yani catcode değişiklikleri) yerel tutmak için bir grup başlatırız, böylece giriş metnini karıştırmazlar.

\let~\catcode
Temel olarak tüm TeX gizleme kodları bu talimatla başlar. Varsayılan olarak, hem düz TeX hem de LaTeX'te, ~karakter ileride kullanılmak üzere bir makro haline getirilebilen bir aktif karakterdir. Ve TeX kodunu garipleştirmek için en iyi araç catcode değişiklikleridir, bu nedenle bu genellikle en iyi seçimdir. Şimdi \catcode`A=13biz yerine ~`A13( =isteğe bağlı) yazabiliriz :

~`A13
Şimdi mektup Aaktif bir karakter ve bir şey yapması için tanımlayabiliriz:

\defA#1{~`#113\gdef}
Aşimdi bir argüman alan bir makro (başka bir karakter olmalı). İlk Tartışmanın catcode aktif hale getirmek için 13 olarak değiştirilir: ~`#113(replace ~tarafından \catcodeve bir ekleme =ve varsa: \catcode`#1=13). Sonunda giriş akışında bir \gdef(global \def) bırakır . Kısacası, Abaşka bir karakteri aktif hale getirir ve tanımına başlar. Hadi deneyelim:

AGG#1{~`#113\global\let}
AGilk önce “aktive eder” Gve yapar \gdef, ardından bir sonraki Gtanımlamaya başlar. Tanımı Gbu çok benzer Abir yerine o hariç \gdefbir does \global\let(bir yok \gletgibi \gdef). Kısacası, Gbir karakteri aktive eder ve onu başka bir şey yapar. Daha sonra kullanacağımız iki komut için kısayollar yapalım:

GFF\else
GHH\fi
Şimdi yerine \elseve \fibasitçe Fve kullanabilirsiniz H. Çok daha kısa :)

AQQ{Q}
Şimdi Abaşka bir makro tanımlamak için tekrar kullanıyoruz Q. Yukarıdaki ifade temel olarak (daha az karışık bir dilde) yapar \def\Q{\Q}. Bu çok ilginç bir tanım değil, ama ilginç bir özelliğe sahip. Kodun bir kısmı, hiç genişlediğinde sadece makro kırmak istiyoruz sürece Qolan Qbenzersiz bir işareti gibi davranır böylece, kendisi (bir deniyor kuark ). \ifxBir makronun argümanının aşağıdaki gibi kuark olup olmadığını test etmek için koşullu kullanabilirsiniz \ifx Q#1:

AII{\ifxQ}
Böylece böyle bir işaretleyici bulduğuna emin olabilirsin. Bu tanımda \ifxve arasındaki boşluğu kaldırdığımı fark et Q. Genellikle bu bir hataya yol açar (sözdiziminin vurgulamasının \ifxQbir şey olduğunu düşündüğünü unutmayın ), ancak şimdi Qcatcode 13 olduğundan , bir kontrol dizisi oluşturamaz. Ancak, bu kuark genişlemesini ya da çünkü sonsuz döngüye takılıp alırsınız değil, dikkatli olun Qgenişleyeceği için Qhangi genişler Qhangi ...

Şimdi ön hazırlıklar yapıldıktan sonra, setterl için uygun algoritmaya gidebiliriz. TeX'in belirteçlenmesi nedeniyle algoritmanın geriye doğru yazılması gerekir. Bunun nedeni bir tanım yaptığınız zaman TeX'in geçerli ayarları kullanarak tanımdaki karakterlere belirteç vermesi (katod atama), örneğin, eğer:

\def\one{E}
\catcode`E=13\def E{1}
\one E

çıktı ise E1, tanımların sırasını değiştirirsem:

\catcode`E=13\def E{1}
\def\one{E}
\one E

çıktı 11. Bunun nedeni, ilk örnekte Etanımdaki tanımın, kod değişikliği yapılmadan önce bir harf (kod kodu 11) olarak belirtilmiş olmasıdır, bu yüzden her zaman bir harf olacaktır E. Bununla birlikte, ikinci örnekte, Eilk önce aktif hale getirildi ve ancak daha sonra \onetanımlandı ve şimdi tanım, Egenişleyen catcode 13'ü içeriyor 1.

Bununla birlikte, bu gerçeği görmezden geleceğim ve tanımları mantıklı (ancak çalışmayan) bir düzen için yeniden sıralayacağım. Aşağıdaki paragraflarda size harfler varsayabiliriz B, C, Dve Eaktiftirler.

\gdef\S#1{\iftrueBH#1 Q }
(önceki sürümde küçük bir hata olduğunu fark edin, yukarıdaki tanımdaki son boşluğu içermiyordu. Sadece bunu yazarken fark ettim. Okumaya devam edin ve neden makroyu düzgün bir şekilde sonlandırmak için buna ihtiyacımız olduğunu göreceksiniz. )
Öncelikle, kullanıcı düzeyinde makro tanımlamak \S. Bu, dostça (?) Bir sözdizimine sahip aktif bir karakter olmamalıdır, bu yüzden gwappins eht setterl için makro böyledir \S. Makro, her zaman gerçek bir koşullu ile başlar \iftrue(kısa sürede neden belli olur) ve ardından eşleşmesi için Bmakroyu H(daha önce tanımladığımız \fi) çağırır \iftrue. Sonra makro argümanını izleriz, #1ardından boşluk ve kuark izleriz Q. Varsayalım \S{hello world}, sonra girdi akışını kullanın.Şuna bakmalıyım: \iftrue BHhello world Q␣(Son boşluğu değiştirdim, böylece sitenin görüntülenmesi onu kodun önceki sürümünde yaptığım gibi yemez). \iftruedoğrudur, bu yüzden genişler ve biz geride kalırız BHhello world Q␣. TeX yok değil kaldırmak \fi( H) şartlı değerlendirilir sonrasına kadar, bunun yerine orada bırakır \fiedilir aslında genişletilmiş. Şimdi Bmakro genişletildi:

ABBH#1 {HI#1FC#1|BH}
BBir olan sınırlandırılmış makro kimin parametre metindir H#1␣argüman arasındaki neyse yani, Hve bir boşluk. Genişlemesine önce giriş akışı Yukarıdaki örnekten devam BIS BHhello world Q␣. Bizlemektedir Hbu (aksi Tex bir hata artıracaktır) gerektiği gibi, daha sonra bir sonraki alan arasında hellove worldbu yüzden, #1bir kelime hello. Ve burada giriş metnini boşluklarda bölmeliyiz. Yay: D genişlemesi Bile, giriş akımı ve yerine geçer, birinci boşluğa kaldırır her up HI#1FC#1|BHile #1olmak hello: HIhelloFChello|BHworld Q␣. BHKuyruk özyinelemesini yapmak için giriş akımında daha sonra yeni olduğuna dikkat edin .Bve sonraki kelimeleri işler. Bu kelime işlendikten sonra B, bir sonraki kelimeyi işlenecek kelime kuark olana kadar işler Q. QSınırlandırılmış makro , argümanın sonunda bir tane B gerektirdiğinden sonraki son boşluğa ihtiyaç vardır . Önceki sürümde (düzenleme geçmişine bakın), eğer kullanırsanız kod yanlış davranır \S{hello world}abc abc( abcs arasındaki boşluk kaybolur).

Tamam, giriş akımına geri: HIhelloFChello|BHworld Q␣. İlk önce başlangıcı tamamlayan H( \fi) var \iftrue. Şimdi bizde var (sözde kodlanmış):

I
  hello
F
  Chello|B
H
world Q␣

I...F...HDüşünce aslında bir olduğunu \ifx Q...\else...\fiyapısı. \ifxKelime (ilk belirteç) halinde alıp test eder olan Qkuark. Eğer öyleyse yapması gereken şey ve icra sonlandığı olduğunu kalır aksi ne var: Chello|BHworld Q␣. Şimdi Cgenişletildi:

ACC#1#2|{D#2Q|#1 }
Birinci bağımsız değişkeni Ctek bir belirteci olacak çaprazlı çok sürece undelimited olup, ikinci bağımsız tarafından sınırlanan |bu nedenle genişlemesi sonra, C(ile #1=hve #2=ellogiriş akımı olması durumunda): DelloQ|h BHworld Q␣. Bildirim başka o |orada konur ve hiçinde hellobundan sonra konur. Değişimin yarısı yapılır; ilk harf sonunda. TeX'te, bir belirteç listesinin ilk belirtecini almak kolaydır. Basit bir makro \def\first#1#2|{#1}, kullandığınızda ilk harfi alır \first hello|. Sonuncusu bir sorundur çünkü TeX her zaman “en küçük, muhtemelen boş” simge listesini argüman olarak alır, bu yüzden birkaç çalışmaya ihtiyacımız var. Belirteç listesindeki bir sonraki öğe D:

ADD#1#2|{I#1FE{}#1#2|H}
Bu Dmakro çevreleyenlerden biridir ve kelimenin tek bir harf olduğu tek durumda yararlıdır. Diyelim ki hellobiz yerine x. Bu durumda, giriş akışı olur DQ|x, daha sonra D(ile genişler #1=Qve #2hiç boş): IQFE{}Q|Hx. Bu, argümanın kuark olduğunu görecek ve içerisindeki yalnızca dizgi için ayrılan yürütmeyi kesecek olan I...F...H( \ifx Q...\else...\fi) bloğuna benzer . (Dönen Diğer durumlarda örneğin), (ile artıracağı ve için): . Yine, kontrol eder ama başarısız ve alacak dalı: . Şimdi bu şeyin son parçası,BxhelloD#1=e#2=lloQIeFE{}elloQ|Hh BHworld Q␣I...F...HQ\elseE{}elloQ|Hh BHworld Q␣E makro genişler:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
Buradaki parametre metni oldukça benzer Cve D; birinci ve ikinci argümanlar reddedilir ve sonuncusu tarafından sınırlandırılır |. Bu gibi giriş akışı görünüm: E{}elloQ|Hh BHworld Q␣daha sonra Egenişler ile ( #1boş #2=eve #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Başka bir I...F...Hkuark blok kontrol (ki görür lve döner false) E{e}lloQ|HHh BHworld Q␣. Şimdi E(yine genişler #1=eboş, #2=lve #3=loQ): IloQleFE{el}loQ|HHHh BHworld Q␣. Ve tekrar I...F...H. Makro, Qbulunana ve truedal alınana kadar birkaç yineleme daha yapar : E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Şimdi kuark bulundu ve şartlı genişletildiği etmektir: oellHHHHh BHworld Q␣. Uf.

Bekle, bunlar nedir? NORMAL MEKTUPLAR? Ah oğlum! Harfler nihayet bulunurlar ve TeX aşağı yazıyor oellsonra bir grup, H( \fi) bulundu ve ile giriş akışı bırakarak (hiçbir şey) genişletilir: oellh BHworld Q␣. Şimdi ilk kelimenin ilk ve son harfleri değiştirildi ve TeX'in bir sonraki bulduğu şey B, bir sonraki kelimenin tüm işlemini tekrarlamak için diğeri .

}
Sonunda gruba geri döndük, böylece tüm yerel görevlerin yerine getirilebilmesi sağlandı. Yerel atamaları harflerin catcode değişikliklerdir A, B, C, ... makro yapıldığı yüzden normal harf anlam dönmek olduğunu ve güvenli metinde kullanılabilir. Ve bu kadar. Şimdi \Sorada tanımlanan makro, metnin yukarıdaki gibi işlenmesini tetikleyecektir.

Bu kodla ilgili ilginç bir şey, tamamen genişletilebilir olmasıdır. Başka bir deyişle, patlayacaklarından endişe etmeden, değişkenleri argümanlarda güvenle kullanabilirsiniz. Bir \iftestteki bir kelimenin son harfinin, ikinci harf ile aynı olup olmadığını (hangi sebepten olursa olsun) kontrol etmek için bile kodu kullanabilirsiniz :

\if\S{here} true\else false\fi % prints true (plus junk, which you would need to handle)
\if\S{test} true\else false\fi % prints false

(Muhtemelen de) wordy açıklama için üzgünüm. Ben de TeXies olmayanlar için mümkün olduğunca net yapmaya çalıştım :)

Sabırsız için özeti

Makro \S, girdiyi Bson bir boşlukla sınırlandırılmış belirteçlerin listelerini alan ve bunları ileten aktif bir karakterle hazırlar C. Co listedeki ilk simgeyi alır ve onu simgeli listenin sonuna taşır ve Dkalanlarla genişler . D“kalanların” boş olup olmadığını kontrol eder, bu durumda tek harfli bir kelime bulunursa hiçbir şey yapmaz; aksi takdirde genişler E. Ekelime listesindeki son harfi bulana kadar belirteç listesinde dolaşır, bulunduğunda bu son harfi terk eder, ardından kelimenin ortasını izler, sonra bunu token akışının sonunda bırakılan ilk harf izler. C.


2
Bunun tam bir açıklamasını çok isterim. Nasıl çalıştığını çok merak ediyorum!
LambdaBeta

1
@LambdaBeta Bunu yapabilirim, ama şu anda değil. Bekle ve ben yaptığımda sana ping gönderirim :)
Phelype Oleinik

1
@LambdaBeta Tamamlandı! Üzgünüm, bazen çok
endişeliyim

13

JavaScript (ES6),  39 adet  36 bayt

@FryAmTheEggman sayesinde 3 bayt kaydedildi

Ayırıcı olarak bir satır beslemesi kullanır.

s=>s.replace(/(.)(.*)(.)/g,'$3$2$1')

Çevrimiçi deneyin!


5
(.)(.*)(.)Toplam Geri Çağırma ifadesi bu mu?
MikeTheLiar

1
@MikeTheLiar Tür sanırım. : D
Arnauld,

Atama, ayırıcıyı içeren dizeyi belirtir.
Cees Timmerman

@CeesTimmerman Ne demek istediğinden emin değilim. Bu kod ayırıcı olarak bir satır beslemesi bekliyor ve bu nedenle girdi olarak satır beslemeli dizeleri alıyor. (TIO bağlantısının altbilgisi, boşlukları satır beslemelerine ve daha sonra okunabilirlik için boşluklara dönüştürür.)
Arnauld

"bir alfabe ASCII karakterinin yanı sıra sınırlayıcı olarak kullanılacak bir karakter daha (her bir kelimeyi ayırmak için) " - Nm, bunun ayrı bir parametre olduğunu sanıyordum.
Cees Timmerman

11

retina ,8 5 bayt

,V,,`

Çevrimiçi deneyin!

Kevin Cruijssen sayesinde 3 bayt kaydedildi !

Ayırıcı olarak yeni bir satır kullanır. Retina'nın ters aşamasını ve bazı sınırlarını kullanıyoruz. İlk limit hangi tersine çevrileceği ile eşleşir, bu yüzden hepsini seçeriz ,. Sonra her bir eşleşmenin ilk ve son harfinin değiştirilmesini istiyoruz, bu nedenle her harfi ,,baştan sona kadar bir aralıkta alan aralıkta sıfır adım boyutu ile alıyoruz .


Dangit, cevabımı güncellemek için dokümanlar arasında sadece böyle bir şey araştırıyordum, ama beni yendin. Bunu biliyordum Vama bunun 1,-2gibi endekslerle kullanılabileceğini bilmiyordum . Güzel bir!
Kevin Cruijssen

1
@KevinCruijssen Biraz aldattım ve bu kum havuzundayken limit aralıklarının nasıl çalıştığını gözden geçirdim :) Hala bir aralığı tersine çevirmekten daha iyi bir yol olması gerektiğini düşünüyorum ama daha kısa bir şey bulamadım.
FryAmTheEggman

2
Limitsiz bir aralık olmadan daha kısa olabileceği konusunda haklısınız, çünkü bu 5 baytlık işler görünüyor (dokümanlardaki Adım Sınırlarının altında örnek olarak verilmiştir).
Kevin Cruijssen

@KevinCruijssen Güzel! Bunu kaçırdığıma inanamıyorum.
FryAmTheEggman

3
Yani, 5 bayt ve sadece 3 farklı karakter? Bu minimalist.
Coeur

9

Pepe , 107 105 bayt

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Çevrimiçi deneyin!

Açıklama:

Yorumlara ilişkin açıklama: command-explanation -> (stack) // explanation

REEe # input -> (R)
REeeEeeeee # push space to last -> (R) // this prevents an infinite loop

rEE # create loop labeled 0 and automatically push 0 
  re # pop 0 -> (r)
  REEEe # go to last item -> (R)
  REEEEEEe # ...then copy the char to other stack
  REEEE # go to first item -> (R)

  rEE # create loop labeled 32 // detect space
    REEEEEEE # move item to other stack (R)
  ree # do this while char != 32

  re # pop 32 -> (r)
  rEEEee # push item (dup to end) -> (r)
  re # ...then pop -> (r)
  rEEEe rEEeE # go to 2nd to last item -> (r)
  RrEEEee # push the item (R flag: dup to first) -> (r)
  rEEee # go to next -> (r) //
  re # ...then pop -> (r)
  reee rEEEEeEEE # out all as char then clear -> (r)
  ReEe # out 32 as char -> (R)
ree # do this while stack != 0

Bu nasıl çalışıyor?
lirtosiast

@lirtosiast açıklama eklendi
u_ndefined


6

laskelH , 71 bayt

h=reverse
s(x:y:o)=a:h(x:r)where(a:r)=h$y:o
s o=o
f=unwords.map s.words

Çevrimiçi deneyin!

Örnek / çıktı:

Swap the first and last letter in each word
This also works with single letter words like a

It is basically just a straight up implementation in which
I for words consisting of two or more letters cons the head
of the reversed tail on the reverse of the original head consed
on the reversed tail

Note that the rules say that we only have to support one kind
of separator - I am choosing spaces Technically it works with
other whitespace as well, but it will turn everything into spaces
in the end Line endings in this example usage are handled separately
to make the example output look nicer
pwaS eht tirsf dna tasl rettel ni hace dorw
shiT olsa sorkw hitw eingls rettel sordw eikl a

tI si yasicallb tusj a ttraighs pu nmplementatioi ni hhicw
I rof sordw gonsistinc fo owt ro eorm setterl sonc eht deah
fo eht deverser lait no eht eeversr fo eht lriginao deah donsec
no eht deverser lait

eotN that eht suler yas that ew ynlo eavh ot tuppors eno dink
fo reparatos - I ma ghoosinc spaces yechnicallT ti sorkw hitw
rtheo ehitespacw sa ,ellw tub ti lilw nurt gverythine onti spaces
ni eht dne einL sndinge ni shit example esagu era dandleh yeparatels
ot eakm eht example tutpuo kool ricen
```

1
Maddede verilen atama, where5 bayttan tasarruf etmek için bir korumaya bağlanabilir: Çevrimiçi deneyin!
Laikoni

1
Orada "Haskell" ismiyle ne yaptığını görüyorum. Aynı şeyi PHP cevabımda da yaptım.
640KB,

5

05AB1E , 10 bayt

#vyRćsRćðJ

Çevrimiçi deneyin!


-3 @Kevin Cruijssen'e teşekkürler .

#           | Split into words.
 vy         | For each word...
   RćsRć    | Reverse, split head, swap, reverse, split tail
        ðJ  | Join by spaces.


1
@KevinCruijssen Gerçekten silmek ve size vermek istiyorum, bu haha ​​argümanlarının sıralanmasında beyin gücünüzün% 99'uydu.
Magic Octopus Urn

1
9 bayt bulundu, ancak yalnızca eski sürümde çalışıyor:|ʒRćsRćJ,
Kevin Cruijssen

1
Ne yazık ki, sahip olmadığımız bir loop_as_long_as_there_are_inputsşeydi, o zaman 8 baytlık bir şey biliyordum: [RćsRćJ,Bu 8 bayt [, teoride asla çıkış yapmıyordu , ancak yalnızca bellek yetersiz olduğunda ya da zaman aşımına uğradığında (TIO'da olduğu gibi) girişte yeni
hat

1
Ne yazık ki ð¡, tek bir kelime girişi mümkün olması gerekir, ancak ð¡εćsÁì}ðýaynı zamanda 10 baytta da çalışır.
Emigna

5

J , 23 17 bayt

({:,1|.}:)&.>&.;:

Çevrimiçi deneyin!


Dönerek ve uygulayarak ilk / son harfleri değiştirmek için çok güzel bir numara 1 A.!
Galen Ivanov

1
1&A.&.(1&|.)-> ({:,1|.}:)ve sonra kaldırabilirsiniz::]
ngn

Şaşırtıcı, teşekkür ederim
FrownyFrog

Gerçekten şaşırtıcı! Bir kez daha çözümün ne kadar basit ve zarif olabileceğine şaşırdım, ancak yalnızca başka biri tarafından yapıldığını gördükten sonra.
Galen Ivanov

4

Yakut ile -p, 42 41 29 bayt

gsub /(\w)(\w*)(\w)/,'\3\2\1'

Çevrimiçi deneyin!



@Shaggy başkanları için teşekkürler. Mesaj geçmişime bakarsanız, 8 ay boyunca cevapsız kaldığımı gösterir, o zaman muhtemelen birkaç notu kaçırdım, haha
Value Ink

Mutabakatın 8 aydan daha fazla bir süre önce değiştiğine kesin olarak karar verdim, ancak bunu kaçırmanız durumunda: “rekabet etmeyen” artık bir şey değil.
Shaggy

Güzel bitti. Bence kurallar uyarınca yeni satırları sınırlayıcı olarak kullanabilir ve s'leri \ws ile değiştirebilirsin ..
histocrat





3

Boşluk , 179 bayt

[N
S S S N
_Create_Label_OUTER_LOOP][S S S N
_Push_n=0][N
S S T   N
_Create_Label_INNER_LOOP][S N
S _Duplicate_n][S N
S _Duplicate_n][S N
S _Duplicate_n][T   N
T   S _Read_STDIN_as_character][T   T   T   _Retrieve_input][S S S T    S T T   N
_Push_11][T S S T   _Subtract_t=input-11][N
T   T   S S N
_If_t<0_jump_to_Label_PRINT][S S S T    N
_Push_1][T  S S S _Add_n=n+1][N
S N
T   N
_Jump_to_Label_INNER_LOOP][N
S S S S N
_Create_Label_PRINT][S S S T    N
_Push_1][T  S S T   _Subtract_n=n-1][S N
S _Duplicate_n][S N
S _Duplicate_n][N
T   S N
_If_n==0_jump_to_Label_PRINT_TRAILING][T    T   T   _Retrieve][T    N
S S _Print_as_character][S S S N
_Push_s=0][N
S S S T N
_Create_Label_PRINT_LOOP][S S S T   N
_Push_1][T  S S S _Add_s=s+1][S N
S _Duplicate_s][S T S S T   S N
_Copy_0-based_2nd_n][T  S S T   _Subtract_i=s-n][N
T   S N
_If_0_Jump_to_Label_PRINT_TRAILING][S N
S _Duplicate_s][T   T   T   _Retrieve][T    N
S S _Print_as_character][N
S T S T N
_Jump_to_Label_PRINT_LOOP][N
S S N
_Create_Label_PRINT_TRAILING][S S S N
_Push_0][T  T   T   _Retrieve][T    N
S S _Print_as_character][S S S T    S S T   N
_Push_9_tab][T  N
S S _Print_as_character][N
S N
S N
_Jump_to_Label_OUTER_LOOP]

Harfler S(boşluk),T (sekme) ve N(yeni satır) yalnızca vurgulama olarak eklenmiştir.
[..._some_action]sadece açıklama olarak eklendi.

Sınırlayıcı olarak sekme. Girdi izleyen bir yeni satır (veya sekme) içermelidir, aksi halde program ne zaman duracağını bilmez, çünkü Whitespace'de girdi almak bir seferde yalnızca bir karakter yapılabilir.

Çevrimiçi deneyin (yalnızca ham alanlar, sekmeler ve yeni satırlarla).

Sahte kodda açıklama:

Boşlukta yalnızca bir yığın ve bir yığın bulunur; burada yığın anahtar ve değere sahip bir haritadır (her iki tam sayı). Girişler, bir seferde yalnızca bir tam sayı veya karakter okunabilir, bunlar her zaman tam sayı olarak yığına yerleştirilir ve daha sonra tanımlanmış yığın adresleriyle (harita anahtarları) alınabilir ve yığına itilebilir. Yaklaşımımda kelimenin tamamını yığın adreslerinde (harita tuşları) depolarım.[0,...,kelime uzunluğu]ve sonra, sekme (veya yeni satır) sınırlayıcı olarak karşılaşıldıktan sonra istediğimiz sırada birer birer basılacak karakterleri alın.

Start OUTER_LOOP:
  Integer n = 0
  Start INNER_LOOP:
    Character c = STDIN as character, saved at heap-address n
    If(c == '\t' OR c == '\n'):
      Jump to PRINT
    n = n + 1
    Go to next iteration of INNER_LOOP

  PRINT:
    n = n - 1
    If(n == 0): (this means it was a single-letter word)
      Jump to PRINT_TRAILING
    Character c = get character from heap-address n
    Print c as character
    Integer s = 0

    Start PRINT_LOOP:
      s = s + 1
      If(s - n == 0):
        Jump to PRINT_TRAILING
      Character c = get character from heap-address s
      Print c as character
      Go to next iteration of PRINT_LOOP

    PRINT_TRAILING:
      Character c = get character from heap-address 0
      Print c as character
      Print '\t'
      Go to next iteration of OUTER_LOOP

Program, TIO'da hiçbiri verilmediğinde bir karakteri okumaya çalıştığında bir hatayla sonlanır (veya vii5ard gibi bazı Whitespace derleyicilerinde bir girdi bekliyor ).


3

Wolfram Dili (Mathematica) , 58 bayt

StringReplace[#,a:u~~w:u..~~b:u:>b<>w<>a/.{u->Except@#2}]&

Çevrimiçi deneyin!

-22 byte @attinat

M.Stern'den -12 bayt


70 bayt kullanılarak StringReplacebirlikte StringExpressions
attinat

1
Kullanılarak 64 byte StringTakeyerine StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman

2
İşte daha doğrudan bir yaklaşım:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern

1
{ve} isteğe bağlıdır :)
M. Stern

1
55 bayt , ayrıca 2-karakter kelime giderir
attinat

2

QuadR , 20 bayt

(\w)(\w*)(\w)
\3\2\1

Basitçe 1, 0 veya daha fazla ve 1 kelime karakterinden oluşan üç çekim grubu oluşturup sıralarını tersine çevirin.

Çevrimiçi deneyin!



2

Japt -S , 10 bayt

Daha kısa bir yaklaşım olması gerektiğine ikna oldum (ve haklıydım ) ama bu şimdilik.

¸ËhJDg)hDÌ

Dene

¸ËhJDg)hDÌ     :Implicit input of string
¸              :Split on spaces
 Ë             :Map each D
  h            :  Set the character at
   J           :    Index -1 to
    Dg         :    The first character in D
      )        :  End set
       h       :  Set the first character to
        DÌ     :    The last character in D
               :Implicit output, joined by spaces

Benim 12 baytımdan çok daha kısa:¸®Ì+Zs1J +Zg
Ignorance'ın yapısı

@EmbodimentofIgnorance, ben de burada başladım, ancak tek karakterli kelimelerde başarısız olmuş olacaktı. Bununla birlikte, bir bayt kaydedebilirsiniz ¸®ÎiZÌ+Zs1J.
Shaggy

1
@EmbodimentofIgnorance 7
Oliver

2

sed, 64 bayt

sed -E 's/\b([[:alpha:]])([[:alpha:]]*)([[:alpha:]])\b/\3\2\1/g'

Tabii, .yerine kullanabiliriz [[:alpha:]], ama aslında olması gerekecek [^ ], bu onu 43'e indirecek, fakat noktalama işaretlerini ve benzeri şeyleri kıracak. Kullanmak [a-zA-Z]onu 55’e çıkarır, bu noktada sadece o tatlı, tatlı okunabilir varlıkların peşindeyim ...
Zengin

2
You do not need to handle punctuation; all of the inputs will only consist of the letters a through z, separated by a delimiter, all of a uniform case.Başka bir deyişle, noktalama işaretlerini kodunuzu "kırma" derken endişelenmenize gerek yoktur ve güvenli bir şekilde gidebilirsiniz [^ ];)
Value Ink

@ValueInk Evet, ama sonra 67 karaktere getiren şey [^ ]olmalı [^[:space:]].
Zengin

"sınırlayıcı", sınırlandırıcının her zaman düzenli bir alan olmasını sağlayabileceğiniz anlamına gelir. Zaten kim bir cümle içinde sekmeleri kullanır?
Value Ink

Tamam. "Kod golfü" gibi görünüyor, aslında işi yapmak yerine topu deliğe atmak için bir dron almanın bir yolunu bulmanız gereken bir oyundur. Boktan karşılama için teşekkürler.
Zengin

2

sed , 34 bayt

Ve muhtemelen, model fikri çoğu RE aracıyla çalışacaktır (ve standart RE ile genişletilmiş RE arasında farklılıklar olduğunu biliyorum).

s,\b\(\w\)\(\w*\)\(\w\)\b,\3\2\1,g

Çevrimiçi deneyin!


1
PPCG'ye Hoşgeldiniz! Regex maçlarının açgözlü doğasının maçtan kesebileceğiniz anlamına geldiğini düşünün \b: Çevrimiçi deneyin!
Değerli Mürekkep

@ValueInk kabul edildi - fakat maçta doğru oldum. İsteğin kaldırılması \b30 byte'a çıkar.
PJF

Gelişmiş regex için -E kullanın ve çıkmamış parantezleri kullanabilirsiniz. .Değiştirilen karakterlerde kullanın ve iki karakter daha kaybedebilirsiniz. Bu sizin 26 bayt aşağı getiriyor; okunabilir en küçük çözümlerden biri. s,\b(.)(\w*)(.)\b,\3\2\1,g
Zengin

1
- hayır, yanılıyorum, sonunda \ws'ye ihtiyacın var . s,\b(\w)(\w*)(\w)\b,\3\2\1,g28 karakter.
Zengin

Güzel iş @ rich, ama dediğim gibi standart ve genişletilmiş RE biliyorum. Sadece standart ve okunabilir hale getirmeyi seçtim. ValueInk'e cevabımda söylemeyi ihmal ettiğim çapalar gerekli olacaktı.
PJF

2

Ruby, 53 bayt

gets.split(" ").map{|z|print z[-1]+z[1..-2]+z[0]," "}

Regex olmadan denedim. Çıktı her sözcüğü yeni bir satıra yazdırır. Bu kurallara aykırıysa, bana bildirin, ben de düzelteceğim.

Ungolfed:

gets.split(" ").map {|z|
    print z[-1] + z[1..-2] + z[0], " "
}

PPCG'ye Hoşgeldiniz! Her bir kelimeyi yeni bir satıra yazdırmak iyi olmalı, fakat eski çözümünüz phiç iyi olmadı çünkü çıktıya tırnak eklendi. Bunun putsyerine her zaman kullanabilirsiniz, çünkü biri yeni satırı otomatik olarak ekler ve bundan daha kısadır print! Ayrıca, splithiçbir argüman olmadan çağırırsanız , otomatik olarak boşluklara ayrılır.
Value Ink

2

8088 Meclisi, IBM PC DOS, 39 38 bayt

$ xxd pwas.com
00000000: d1ee ac8a c8fd 03f1 c604 244e 8bfe ac3c  ..........$N...<
00000010: 2075 098a 2586 6402 8825 8bfe e2f0 b409   u..%.d..%......
00000020: ba82 00cd 21c3

unassembled:

D1 EE       SHR  SI, 1          ; point SI to DOS PSP (080H) 
AC          LODSB               ; load string length into AL 
8A C8       MOV  CL, AL         ; load string length into CX for loop
FD          STD                 ; set LODSB to decrement 
03 F1       ADD  SI, CX         ; point SI to end of string 
C6 04 24    MOV  BYTE PTR[SI], '$' ; put a '$' DOS string terminator at end 
4E          DEC  SI             ; start at last char of word 
8B FE       MOV  DI, SI         ; point DI to last char of word 
        CHR_LOOP: 
AC          LODSB               ; load next (previous?) char into AL 
3C 20       CMP  AL, ' '        ; is it a space? 
75 0A       JNE  END_CHR        ; if so, continue loop 
8A 25       MOV  AH, [DI]       ; put last char in AH 
86 64 02    XCHG AH, [SI][2]    ; swap memory contents of first char with last 
                                ; (unfortunately XCHG cannot swap mem to mem)
88 25       MOV  [DI], AH       ; put first char value into last char position 
8B FE       MOV  DI, SI         ; point DI last char of word 
        END_CHR:
E2 EF       LOOP CHR_LOOP       ; continue loop 
B4 09       MOV  AH, 9          ; DOS display string function 
BA 0082     MOV  DX, 082H       ; output string is at memory address 82H 
CD 21       INT  21H            ; display string to screen 
C3          RET                 ; return to DOS 

Bağımsız PC DOS çalıştırılabilir. Komut satırı ile giriş, ekrana çıkış.

enter image description here

PWAS.COM dosyasını indirin ve test edin .



1

Toplu iş, 141 bayt

@set t=
@for %%w in (%*)do @call:c %%w
@echo%t%
@exit/b
:c
@set s=%1
@if not %s%==%s:~,1% set s=%s:~-1%%s:~1,-1%%s:~,1%
@set t=%t% %s%

Komut satırı parametreleri olarak girdi alır. Dize manipülasyonu en iyi şekilde Batch'te cüretkar ve özel harfli tek harfli kelimeler kullanmak yardımcı olmuyor.




1

Java, 110 109 bayt

Bir sınırlayıcı için yeni bir satır kullanarak -1 bayt

s->{int l;for(var i:s.split("\n"))System.out.println(i.charAt(l=i.length()-1)+i.substring(1,l)+i.charAt(0));}

TIO


Bu tek harfli kelimeler için işe yarıyor mu?
Neil

@Hayır hayır çünkü ben kötüyüm. Sonra tamir ederim.
Benjamin Urquhart

109 sınırlayıcı olarak newline kullanarak
Ignorance uygulaması

1

Haskell , 75 74 bayt

Cubic tarafından işaret edilen ve 1 bayt golf oynadığı bir hata düzeltildi.

f=unwords.map(#v).words
x#g=g(r$tail x)++[x!!0]
r=reverse
v[]=[]
v x=r$x#r

Çevrimiçi deneyin!


map gdaha kısadır(g<$>)
Kübik

1
Also, if you look at your test case you'll see it doesn't work for one letter words, it turns a into aa
Cubic

1

Scala, 100 bytes

(b:String,c:String)=>b.split(c)map(f=>f.tail.lastOption++:(f.drop(1).dropRight(1)+f.head))mkString c

1

T-SQL, 126 bytes

SELECT STRING_AGG(STUFF(STUFF(value,1,1,RIGHT(value,1)),LEN(value),1,LEFT(value,1)),' ')
FROM STRING_SPLIT((SELECT*FROM t),' ')

Input is via a pre-existing table t with varchar field v, per our IO standards.

Reading from back to front, STRING_SPLIT breaks a string into individual rows via a delimiter, STUFF modifies the characters at the specified positions, then STRING_AGG mashes them back together again.

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.