pwaS eht tirsf dna tasl setterl untuk hore dorw


30

Atau, "Tukar huruf pertama dan terakhir dari setiap kata"

Tantangan Anda adalah, mengingat serangkaian karakter ASCII alfabet serta satu karakter lain untuk digunakan sebagai pembatas (untuk memisahkan setiap kata), menukar huruf pertama dan terakhir dari setiap kata. Jika ada kata satu karakter, biarkan saja.

Contoh / testcases menggunakan huruf kecil dan spasi sebagai pembatas.

Anda tidak perlu menangani tanda baca; semua input hanya akan terdiri dari huruf a sampai z, dipisahkan oleh pembatas, semua kasus seragam.

Misalnya, dengan string "hello world":

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"

CATATAN: pembatas tidak perlu dimasukkan secara terpisah. Pembatas hanyalah karakter yang digunakan untuk memisahkan kata-kata. Itu bisa apa saja. Saya ingin membiarkan opsi terbuka untuk pegolf kreatif, jadi saya tidak ingin membatasi hanya ruang atau garis baru. Pembatas hanyalah karakter yang memisahkan kata dalam string input.

Kasus uji:

"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
Bagaimana seharusnya tanda baca diperlakukan? Hello, world!menjadi ,elloH !orldw(menukar tanda baca sebagai huruf) atau oellH, dorlw!(mempertahankan tanda baca di tempat)?
Phelype Oleinik

3
@PhelypeOleinik Anda tidak perlu menangani tanda baca; semua input hanya akan terdiri dari huruf a hingga z, dan semua case yang seragam.
Kamerad SparklePony

4
Paragraf kedua berbunyi serta satu karakter lain untuk digunakan sebagai pembatas sedangkan yang keempat dibaca dengan spasi . Yang mana?
Adám

@ Adám Setiap karakter non-alfabet. Saya akan mengedit untuk mengklarifikasi.
Kamerad SparklePony

1
@BenjaminUrquhart Ya. Anda dapat mengambil input sebagai argumen fungsi jika Anda mau.
Kamerad SparklePony

Jawaban:


59

TeX, 216 byte (masing-masing 4 baris, 54 karakter)

Karena ini bukan tentang jumlah byte, ini tentang kualitas output typeset :-)

{\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 }}

Cobalah secara Online! (Overleaf; tidak yakin cara kerjanya)

File tes lengkap:

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

Keluaran:

masukkan deskripsi gambar di sini


Untuk LaTeX Anda hanya perlu boilerplate:

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

Penjelasan

TeX adalah binatang aneh. Membaca kode normal dan memahaminya adalah suatu prestasi tersendiri. Memahami kode TeX yang dikaburkan melangkah lebih jauh. Saya akan mencoba membuat hal ini dapat dimengerti oleh orang-orang yang juga tidak mengenal TeX, jadi sebelum kita mulai di sini adalah beberapa konsep tentang TeX untuk membuat hal-hal lebih mudah diikuti:

Untuk (tidak begitu) pemula TeX mutlak

  • Pertama, dan yang paling item yang penting dalam daftar ini: kode tidak tidak harus dalam bentuk persegi panjang, meskipun budaya pop mungkin menyebabkan Anda berpikir begitu .

  • TeX adalah bahasa ekspansi makro. Anda dapat, sebagai contoh, mendefinisikan \def\sayhello#1{Hello, #1!}dan kemudian menulis \sayhello{Code Golfists}untuk mendapatkan TeX untuk dicetak Hello, Code Golfists!. Ini disebut "undelimited macro", dan untuk memberikannya parameter pertama (dan hanya, dalam hal ini) Anda melampirkannya dalam kurung kurawal. TeX menghapus kawat gigi itu ketika makro mengambil argumen. Anda dapat menggunakan hingga 9 parameter: \def\say#1#2{#1, #2!}lalu \say{Good news}{everyone}.

  • Counterpart macro undelimited yang, tidak mengejutkan, yang dibatasi :) Anda bisa membuat definisi sebelumnya anak laki-laki lebih semantical : \def\say #1 to #2.{#1, #2!}. Dalam hal ini parameter diikuti oleh apa yang disebut teks parameter . Teks parameter tersebut membatasi argumen makro ( #1dibatasi oleh ␣to␣, spasi yang disertakan, dan #2dibatasi oleh .). Setelah definisi itu, Anda dapat menulis \say Good news to everyone., yang akan diperluas ke Good news, everyone!. Bagus bukan? :) Namun argumen yang dibatasi adalah (mengutip TeXbook ) “urutan token terpendek (mungkin kosong) dengan {...}grup bertumpuk dengan benar yang diikuti dalam input oleh daftar token non-parameter khusus ini”. Ini berarti perluasan dari\say Let's go to the mall to Martinakan menghasilkan kalimat yang aneh. Dalam hal ini Anda akan perlu untuk “menyembunyikan” yang pertama ␣to␣dengan {...}: \say {Let's go to the mall} to Martin.

  • Sejauh ini baik. Sekarang segalanya mulai menjadi aneh. Ketika TeX membaca sebuah karakter (yang didefinisikan oleh "kode karakter"), TeX akan memberikan karakter itu "kode kategori" (catcode, untuk teman-teman :) yang mendefinisikan apa arti karakter itu. Kombinasi kode karakter dan kategori ini membuat token (lebih lanjut tentang itu di sini , misalnya). Yang menarik bagi kami di sini pada dasarnya adalah:

    • catcode 11 , yang mendefinisikan token yang dapat membuat urutan kontrol (nama mewah untuk makro). Secara default semua huruf [a-zA-Z] adalah catcode 11, jadi saya bisa menulis \hello, yang merupakan satu urutan kontrol tunggal, sedangkan \he11ourutan kontrol \hediikuti oleh dua karakter 1, diikuti oleh huruf o, karena 1bukan catcode 11. Jika saya lakukan \catcode`1=11, sejak saat itu \he11oakan menjadi satu urutan kontrol. Satu hal penting adalah bahwa kode-kode ditetapkan ketika TeX pertama kali melihat karakter di tangan, dan kode seperti itu dibekukan ... SELAMANYA! (syarat dan ketentuan berlaku)

    • catcode 12 , yang merupakan sebagian besar karakter lain, seperti 0"!@*(?,.-+/dan sebagainya. Mereka adalah jenis catcode yang paling tidak istimewa karena hanya berfungsi untuk menulis hal-hal di atas kertas. Tapi, hei, siapa yang menggunakan TeX untuk menulis?!? (sekali lagi, syarat dan ketentuan berlaku)

    • catcode 13 , yang mana sih :) Sungguh. Berhentilah membaca dan lakukan sesuatu dari hidup Anda. Anda tidak ingin tahu apa itu catcode 13. Pernah dengar hari Jumat, tanggal 13? Tebak dari mana namanya berasal! Lanjutkan dengan risiko Anda sendiri! Karakter catcode 13, juga disebut karakter "aktif", bukan hanya karakter lagi, itu adalah makro itu sendiri! Anda dapat mendefinisikannya untuk memiliki parameter dan memperluas ke sesuatu seperti yang kita lihat di atas. Setelah Anda melakukan \catcode`e=13Anda berpikir Anda bisa melakukannya \def e{I am the letter e!}, TAPI. KAMU. TIDAK BISA! ebukan surat lagi, jadi \defbukankah \defAnda tahu, itu \d e f! Oh, pilih surat lain yang Anda katakan? Baik! \catcode`R=13 \def R{I am an ARRR!}. Baiklah, Jimmy, coba! Saya berani Anda melakukan itu dan menulis Rkode Anda! Itulah yang dimaksud dengan catcode 13. SAYA TENANG! Mari kita lanjutkan.

  • Oke, sekarang untuk pengelompokan. Ini cukup mudah. Tugas apa pun ( \defmerupakan operasi penugasan, \let(kami akan membahasnya) adalah tugas lain) yang dilakukan dalam suatu grup dikembalikan ke posisi semula sebelum grup itu dimulai kecuali tugas itu bersifat global. Ada beberapa cara untuk memulai grup, salah satunya adalah dengan karakter catcode 1 dan 2 (oh, kode cat lagi). Secara default {adalah catcode 1, atau begin-group, dan }catcode 2, atau end-group. Contoh: \def\a{1} \a{\def\a{2} \a} \aIni mencetak 1 2 1. Di luar grup \aada 1, lalu di dalamnya didefinisikan ulang 2, dan ketika grup berakhir, ia dikembalikan ke 1.

  • The \letoperasi tugas operasi lain seperti \def, tapi agak berbeda. Dengan \defAnda menentukan makro yang akan diperluas ke hal-hal, dengan \letAnda membuat salinan dari hal-hal yang sudah ada. Setelah \let\blub=\def( =opsional) Anda dapat mengubah awal econtoh dari item catcode 13 di atas \blub e{...dan bersenang-senang dengan yang itu. Atau lebih baik, bukannya melanggar hal-hal yang Anda dapat memperbaiki (yang akan Anda lihat itu!) Yang Rmisalnya: \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Pertanyaan cepat: dapatkah Anda mengganti nama \newR?

  • Akhirnya, yang disebut "ruang palsu". Ini semacam topik yang tabu karena ada orang yang mengklaim bahwa reputasi yang diperoleh di TeX - LaTeX Stack Exchange dengan menjawab pertanyaan "ruang palsu" tidak boleh dipertimbangkan, sementara yang lain dengan sepenuh hati tidak setuju. Dengan siapa Anda setuju? Tempatkan taruhan Anda! Sementara itu: TeX memahami jeda baris sebagai spasi. Cobalah untuk menulis beberapa kata dengan jeda baris (bukan baris kosong ) di antaranya. Sekarang tambahkan %di akhir baris ini. Sepertinya Anda “berkomentar” pada ruang-ruang ujung ini. Itu dia :)

(Semacam) tidak mengubah kode

Mari kita buat persegi panjang itu menjadi sesuatu (bisa dibilang) lebih mudah diikuti:

{
\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 }
}

Penjelasan dari setiap langkah

setiap baris berisi satu instruksi tunggal. Mari kita pergi satu per satu, membedah mereka:

{
Pertama-tama kita memulai sebuah kelompok untuk menjaga beberapa perubahan (yaitu perubahan catcode) lokal sehingga mereka tidak mengacaukan teks input.

\let~\catcode
Pada dasarnya semua kode kebingungan TeX dimulai dengan instruksi ini. Secara default, baik dalam TeX polos dan LaTeX, ~karakter adalah karakter aktif yang dapat dibuat menjadi makro untuk digunakan lebih lanjut. Dan alat terbaik untuk mengubah kode TeX adalah perubahan catcode, jadi ini umumnya pilihan terbaik. Sekarang alih-alih \catcode`A=13kita dapat menulis ~`A13( =ini opsional):

~`A13
Sekarang surat itu Aadalah karakter aktif, dan kita dapat mendefinisikannya untuk melakukan sesuatu:

\defA#1{~`#113\gdef}
Asekarang merupakan makro yang mengambil satu argumen (yang seharusnya merupakan karakter lain). Pertama-tama catcode argumen diubah menjadi 13 untuk membuatnya aktif: ~`#113(ganti ~dengan \catcodedan tambahkan =dan Anda punya :) \catcode`#1=13. Akhirnya ia meninggalkan \gdef(global \def) dalam aliran input. Singkatnya, Abuat karakter lain aktif dan mulai definisinya. Mari kita coba:

AGG#1{~`#113\global\let}
AG"aktifkan" pertama Gdan lakukan \gdef, yang diikuti oleh yang berikutnya Gmemulai definisi. Definisi Gini sangat mirip dengan A, kecuali bahwa alih-alih \gdefitu melakukan \global\let(tidak ada \gletseperti \gdef). Singkatnya, Gmengaktifkan karakter dan membuatnya menjadi sesuatu yang lain. Mari kita buat pintasan untuk dua perintah yang akan kita gunakan nanti:

GFF\else
GHH\fi
Sekarang alih-alih \elsedan \fikita cukup menggunakan Fdan H. Jauh lebih pendek :)

AQQ{Q}
Sekarang kita gunakan Alagi untuk mendefinisikan makro lain Q,. Pernyataan di atas pada dasarnya tidak (dalam bahasa yang kurang dikaburkan) \def\Q{\Q}. Ini bukan definisi yang sangat menarik, tetapi memiliki fitur yang menarik. Kecuali Anda ingin memecah beberapa kode, satu-satunya makro yang berkembang Qadalah Qdirinya sendiri, sehingga berfungsi seperti penanda unik (disebut quark ). Anda bisa menggunakan \ifxpersyaratan untuk menguji apakah argumen makro adalah quark dengan \ifx Q#1:

AII{\ifxQ}
sehingga Anda dapat yakin bahwa Anda menemukan spidol tersebut. Perhatikan bahwa dalam definisi ini saya menghapus ruang antara \ifxdan Q. Biasanya ini akan menyebabkan kesalahan (perhatikan bahwa highlight sintaksis berpikir itu \ifxQadalah satu hal), tetapi karena sekarang Qadalah katak 13 maka tidak dapat membentuk urutan kontrol. Namun, berhati-hatilah untuk tidak memperluas kuark ini atau Anda akan terjebak dalam loop tak terbatas karena Qmemperluas Qyang memperluas ke Qmana ...

Sekarang setelah pendahuluan telah selesai, kita dapat pergi ke algoritma yang tepat untuk mengatur setterl. Karena tokenization TeX, algoritma harus ditulis mundur. Ini karena pada saat Anda melakukan definisi, TeX akan melakukan tokenize (menetapkan kode) ke karakter dalam definisi menggunakan pengaturan saat ini jadi, misalnya, jika saya lakukan:

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

hasilnya adalah E1, sedangkan jika saya mengubah urutan definisi:

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

outputnya adalah 11. Ini karena pada contoh pertama Edefinisi dalam tokenized sebagai huruf (catcode 11) sebelum perubahan catcode, jadi itu akan selalu menjadi huruf E. Namun, pada contoh kedua, Epertama kali diaktifkan, dan baru kemudian \oneditetapkan, dan sekarang definisi tersebut berisi katak 13 Eyang diperluas 1.

Namun, saya akan mengabaikan fakta ini dan menyusun ulang definisi untuk memiliki urutan logis (tetapi tidak berfungsi). Dalam paragraf berikut Anda dapat mengasumsikan bahwa surat-surat B, C, D, dan Eaktif.

\gdef\S#1{\iftrueBH#1 Q }
(perhatikan ada bug kecil di versi sebelumnya, itu tidak mengandung ruang terakhir dalam definisi di atas. Saya hanya memperhatikannya saat menulis ini. Baca terus dan Anda akan melihat mengapa kita membutuhkannya untuk menghentikan makro dengan benar. )
Pertama kita mendefinisikan makro tingkat pengguna \S,. Yang ini seharusnya tidak menjadi karakter aktif untuk memiliki sintaks ramah (?), Jadi makro untuk gwappins dan setterl adalah \S. Makro dimulai dengan kondisi selalu benar \iftrue(akan segera menjadi jelas mengapa), dan kemudian memanggil Bmakro diikuti oleh H(yang telah kita tentukan sebelumnya \fi) untuk mencocokkan \iftrue. Lalu kita meninggalkan argumen makro #1diikuti oleh spasi dan oleh quark Q. Misalkan kita gunakan \S{hello world}, maka input streamakan terlihat seperti ini: \iftrue BHhello world Q␣(Saya mengganti ruang terakhir dengan sehingga rendering situs tidak memakannya, seperti yang saya lakukan pada versi kode sebelumnya). \iftrueitu benar, jadi itu mengembang dan kita dibiarkan BHhello world Q␣. TeX tidak menghapus \fi( H) setelah kondisi dievaluasi, melainkan membiarkannya di sana sampai benar\fi - benar diperluas. Sekarang Bmakro diperluas:

ABBH#1 {HI#1FC#1|BH}
Badalah makro terbatas yang memiliki parameter teks H#1␣, jadi argumennya adalah apa pun yang ada di antara Hdan spasi. Melanjutkan contoh di atas aliran input sebelum perluasan Bis BHhello world Q␣. Bdiikuti oleh H, sebagaimana mestinya (jika TeX akan menimbulkan kesalahan), maka ruang berikutnya adalah antara hellodan world, begitu #1juga kata hello. Dan di sini kita harus membagi teks input di spasi. Yay: D Perluasan Bmenghapus segala sesuatu sampai ke ruang pertama dari input stream dan menggantikan dengan HI#1FC#1|BHdengan #1menjadi hello: HIhelloFChello|BHworld Q␣. Perhatikan bahwa ada yang baru BHnanti dalam aliran input, untuk melakukan rekursi ekorBdan memproses kata-kata selanjutnya. Setelah kata ini diproses, Bproses kata berikutnya hingga kata yang akan diproses adalah kuark Q. Ruang terakhir setelah Qdiperlukan karena makro dibatasi B membutuhkan satu di akhir argumen. Dengan versi sebelumnya (lihat sunting histori) kode akan bertingkah jika Anda menggunakan \S{hello world}abc abc(ruang antara abcs akan lenyap).

OK, kembali ke input stream: HIhelloFChello|BHworld Q␣. Pertama ada H( \fi) yang melengkapi inisial \iftrue. Sekarang kita punya ini (pseudocoded):

I
  hello
F
  Chello|B
H
world Q␣

The I...F...Hberpikir sebenarnya adalah \ifx Q...\else...\fistruktur. The \ifxpemeriksaan tes jika (pertama tanda yang) kata meraih adalah Qquark. Jika tidak ada yang lain untuk melakukan dan berakhir eksekusi, jika apa yang tersisa adalah: Chello|BHworld Q␣. Sekarang Cdiperluas:

ACC#1#2|{D#2Q|#1 }
Argumen pertama Cadalah undelimited, jadi kecuali bersiap akan menjadi tanda tunggal, Argumen kedua dibatasi oleh |, jadi setelah ekspansi C(dengan #1=hdan #2=ello) input stream adalah: DelloQ|h BHworld Q␣. Perhatikan bahwa lain |yang diletakkan di sana, dan hdari hellodiletakkan setelah itu. Setengah swapping dilakukan; huruf pertama ada di akhir. Di TeX, mudah untuk mengambil token pertama dari daftar token. Makro sederhana \def\first#1#2|{#1}mendapatkan huruf pertama saat Anda menggunakan \first hello|. Yang terakhir adalah masalah karena TeX selalu mengambil daftar token "terkecil, mungkin kosong" sebagai argumen, jadi kita perlu beberapa solusi. Item berikutnya dalam daftar token adalah D:

ADD#1#2|{I#1FE{}#1#2|H}
DMakro ini adalah salah satu solusi dan berguna dalam kasus tunggal di mana kata memiliki satu huruf. Andaikan hellokita tidak melakukannya x. Dalam hal ini input stream akan DQ|x, maka Dakan memperluas (dengan #1=Q, dan #2mengosongkan) ke: IQFE{}Q|Hx. Ini mirip dengan blok I...F...H( \ifx Q...\else...\fi) di B, yang akan melihat bahwa argumen adalah quark dan akan mengganggu eksekusi hanya menyisakan xuntuk pengaturan huruf. Dalam kasus lain (kembali ke hellocontoh), Dakan memperluas (dengan #1=edan #2=lloQ) ke: IeFE{}elloQ|Hh BHworld Q␣. Sekali lagi, I...F...Hakan memeriksa Qtapi akan gagal dan mengambil \elsecabang: E{}elloQ|Hh BHworld Q␣. Sekarang bagian terakhir dari hal ini, theE makro akan berkembang:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
Teks parameter di sini sangat mirip dengan Cdan D; argumen pertama dan kedua tidak didahulukan, dan yang terakhir dibatasi oleh |. Input stream terlihat seperti ini: E{}elloQ|Hh BHworld Q␣, kemudian Emengembang (dengan #1kosong, #2=edan #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Lain I...F...Hblok cek untuk quark (yang melihat ldan kembali false): E{e}lloQ|HHh BHworld Q␣. Sekarang Ememperluas lagi (dengan #1=ekosong, #2=ldan #3=loQ): IloQleFE{el}loQ|HHHh BHworld Q␣. Dan lagi I...F...H. Makro melakukan beberapa iterasi lagi sampai Qakhirnya ditemukan dan truecabang diambil: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Sekarang quark ditemukan dan mengembang bersyarat untuk: oellHHHHh BHworld Q␣. Fiuh.

Oh, tunggu, apa ini? SURAT NORMAL? Oh Boy! Surat-surat yang akhirnya menemukan dan TeX menuliskan oell, kemudian sekelompok H( \fi) ditemukan dan diperluas (apa-apa) meninggalkan input stream dengan: oellh BHworld Q␣. Sekarang kata pertama memiliki huruf pertama dan terakhir ditukar dan apa TeX menemukan selanjutnya adalah yang lain Buntuk mengulangi seluruh proses untuk kata berikutnya.

}
Akhirnya kami mengakhiri grup mulai kembali ke sana sehingga semua tugas lokal dibatalkan. Tugas lokal adalah perubahan catcode huruf A, B, C, ... yang dibuat macro sehingga mereka kembali ke surat arti normal mereka dan dapat digunakan dengan aman dalam teks. Dan itu saja. Sekarang \Smakro yang didefinisikan kembali di sana akan memicu pemrosesan teks seperti di atas.

Satu hal yang menarik tentang kode ini adalah bahwa kode ini sepenuhnya dapat dikembangkan. Artinya, Anda bisa menggunakannya dengan aman dalam memindahkan argumen tanpa khawatir itu akan meledak. Anda bahkan dapat menggunakan kode untuk memeriksa apakah huruf terakhir dari sebuah kata sama dengan yang kedua (untuk alasan apa pun Anda membutuhkannya) dalam \ifujian:

\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

Maaf untuk penjelasan bertele-tele (mungkin terlalu). Saya mencoba membuatnya sejelas mungkin untuk non TeXies juga :)

Ringkasan untuk yang tidak sabar

Makro \Smendahului input dengan karakter aktif Byang mengambil daftar token yang dibatasi oleh ruang final dan meneruskannya ke C. Cmengambil token pertama dalam daftar itu dan memindahkannya ke akhir daftar token dan memperluas Ddengan apa yang tersisa. Dmemeriksa apakah "apa yang tersisa" kosong, dalam hal ditemukan satu kata, tidak melakukan apa-apa; jika tidak mengembang E. Eloop melalui daftar token sampai menemukan huruf terakhir dalam kata, ketika ditemukan meninggalkan huruf terakhir, diikuti oleh tengah kata, yang kemudian diikuti oleh huruf pertama yang tersisa di ujung token stream oleh C.


2
Saya ingin penjelasan lengkap tentang ini. Saya sangat ingin tahu bagaimana cara kerjanya!
LambdaBeta

1
@LambdaBeta saya bisa melakukannya, tetapi tidak sekarang. Tunggu
sebentar

1
@LambdaBeta Selesai! Maaf, terkadang saya terlalu bertele-tele :-)
Phelype Oleinik

13

JavaScript (ES6),  39  36 byte

Disimpan 3 byte berkat @FryAmTheEggman

Menggunakan umpan baris sebagai pemisah.

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

Cobalah online!


5
(.)(.*)(.)Apakah itu emotikon Total Recall?
MikeTheLiar

1
@ MikeTheLiar, saya kira. : D
Arnauld

Tugas menentukan string berisi pemisah.
Cees Timmerman

@ CeesTimmerman Saya tidak yakin apa yang Anda maksud. Kode ini mengharapkan umpan baris sebagai pemisah dan karenanya mengambil string dengan umpan baris sebagai input. (Footer dari tautan TIO mengubah spasi menjadi umpan baris dan kemudian kembali ke spasi untuk dibaca.)
Arnauld

"diberi serangkaian karakter ASCII alfabet serta satu karakter lain untuk digunakan sebagai pembatas (untuk memisahkan setiap kata) " - Nm, saya pikir itu adalah parameter yang terpisah.
Cees Timmerman

11

Retina ,8 5 byte

,V,,`

Cobalah online!

Disimpan 3 byte berkat Kevin Cruijssen !

Menggunakan baris baru sebagai pemisah. Kami menggunakan tahap mundur Retina dan beberapa batasan. Batas pertama adalah yang cocok untuk menerapkan pembalikan, jadi kami memilih semuanya ,. Lalu kami ingin huruf pertama dan terakhir dari setiap pertandingan ditukar, jadi kami mengambil setiap huruf dalam rentang ,,yang diterjemahkan ke kisaran dari awal hingga akhir dengan ukuran langkah nol.


Dangit, saya baru saja mencari melalui dokumen untuk hal ini untuk memperbarui jawaban saya, tetapi Anda mengalahkan saya untuk itu. Saya tahu V, tetapi tidak tahu itu bisa digunakan dengan indeks 1,-2seperti itu. Yang bagus!
Kevin Cruijssen

1
@KevinCruijssen Saya sedikit curang dan mengulas bagaimana batas batas bekerja saat ini berada di kotak pasir :) Saya masih merasa harus ada cara yang lebih baik daripada membalikkan rentang tetapi saya belum dapat menemukan yang lebih pendek.
FryAmTheEggman

2
Anda memang benar bahwa itu bisa lebih pendek tanpa batas-batas, karena tampaknya ini 5-byter bekerja (diberikan sebagai contoh di bagian bawah Batas Langkah dalam dokumen).
Kevin Cruijssen

@KevinCruijssen Bagus! Tidak percaya saya melewatkan itu.
FryAmTheEggman

3
Jadi, 5 byte dan hanya 3 karakter yang berbeda? Itu minimalis.
Cœur

9

Pepe , 107 105 byte

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Cobalah online!

Penjelasan:

Notasi pada komentar: 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

Bagaimana cara kerjanya?
lirtosiast

@lirtosiast penjelasan ditambahkan
u_ndefined


6

laskelH , 71 byte

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

Cobalah online!

Contoh dalam / output:

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
Tugas dalam whereklausa dapat dipindahkan ke penjaga yang mengikat untuk menghemat 5 byte: Cobalah secara online!
Laikoni

1
Saya melihat apa yang Anda lakukan di sana dengan nama "Haskell" di judulnya. Saya melakukan hal yang sama pada jawaban PHP saya.
640KB

5

05AB1E , 10 byte

#vyRćsRćðJ

Cobalah online!


-3 Terima kasih kepada @Kevin Cruijssen .

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


1
@KevinCruijssen Saya sejujurnya ingin menghapusnya dan memberikannya kepada Anda, itu adalah 99% kekuatan otak Anda dalam memesan argumen haha.
Magic Gurita Guci

1
Ditemukan 9-byter, tetapi hanya berfungsi dalam versi lawas:|ʒRćsRćJ,
Kevin Cruijssen

1
Sayang sekali kita tidak memiliki loop_as_long_as_there_are_inputs, maka saya akan tahu 8-byter: [RćsRćJ,8-byter ini menggunakan [tidak pernah output dalam teori Namun, hanya ketika Anda kehabisan memori atau waktu habis seperti pada TIO (dan itu membutuhkan trailing baris baru dalam input, jika tidak maka akan tetap menggunakan kata terakhir) ..
Kevin Cruijssen

1
Sayangnya Anda membutuhkan ð¡input kata tunggal, tetapi ð¡εćsÁì}ðýjuga bekerja pada 10 byte.
Emigna

5

J , 23 17 byte

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

Cobalah online!


Trik yang sangat bagus untuk menukar huruf pertama / terakhir dengan memutar dan menerapkan 1 A.!
Galen Ivanov

1
1&A.&.(1&|.)-> ({:,1|.}:)dan kemudian Anda dapat menghapus::]
ngn

Luar biasa, terima kasih
FrownyFrog

Sangat menakjubkan! Sekali lagi saya kagum betapa sederhana dan elegan solusinya, tetapi hanya setelah saya melihatnya dilakukan oleh orang lain.
Galen Ivanov

4

Ruby dengan -p, 42 41 29 byte

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

Cobalah online!



@Shaggy, terima kasih atas perhatiannya. Jika Anda melihat riwayat kiriman saya, itu menunjukkan bahwa saya pergi selama 8 bulan tanpa jawaban, jadi saya mungkin melewatkan beberapa memo selama waktu itu, haha
Value Ink

Cukup yakin konsensus telah diubah lebih dari 8 bulan yang lalu tetapi untuk berjaga-jaga jika Anda melewatkannya: "tidak bersaing" juga tidak lagi berarti.
Shaggy

Bagus sekali. Saya pikir di bawah aturan Anda dapat menggunakan baris baru sebagai pembatas Anda dan mengganti \ws dengan .s.
histokrat





3

Ruang putih , 179 byte

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

Huruf S(spasi), T(tab), dan N(baris baru) ditambahkan hanya sebagai penyorotan.
[..._some_action]ditambahkan sebagai penjelasan saja.

Tab sebagai pembatas. Input harus mengandung baris baru (atau tab), jika tidak program tidak tahu kapan harus berhenti, karena mengambil input di Whitespace hanya dapat dilakukan satu karakter pada satu waktu.

Cobalah online (dengan spasi, tab, dan hanya baris baru).

Penjelasan dalam pseudo-code:

[0,...,word_length] , dan kemudian ambil karakter untuk dicetak satu per satu dalam urutan yang kita inginkan setelah tab (atau baris baru) ditemukan sebagai pembatas.

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 berakhir dengan kesalahan ketika mencoba membaca karakter ketika tidak ada yang diberikan dalam TIO (atau hang menunggu input di beberapa kompiler Whitespace seperti vii5ard ).


3

Bahasa Wolfram (Mathematica) , 58 byte

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

Cobalah online!

-22 byte dari @attinat

-12 byte dari @ M.Stern


70 byte menggunakan StringReplacedengan StringExpressions
attinat

1
64 byte menggunakan StringTakesebagai ganti StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman

2
Berikut adalah pendekatan yang lebih langsung:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern

1
{dan} adalah opsional :)
M. Stern

1
55 byte , juga memperbaiki kata
attinat

2

QuadR , 20 byte

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

Cukup buat tiga kelompok pengambilan yang terdiri dari 1, 0-atau-lebih, dan 1 karakter kata, lalu balikkan urutannya.

Cobalah online!



2

Japt -S , 10 byte

Yakin harus ada pendekatan yang lebih pendek (dan saya benar ) tetapi ini akan dilakukan untuk saat ini.

¸ËhJDg)hDÌ

Cobalah

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

Jauh lebih pendek dari byter 12 saya:¸®Ì+Zs1J +Zg
Perwujudan Ketidaktahuan

@EmbodimentofIgnorance, di situlah saya mulai juga, tetapi akan gagal pada kata-kata karakter tunggal. Anda bisa menyimpan byte pada itu, dengan ¸®ÎiZÌ+Zs1J.
Shaggy

1
@EmbodimentofIgnorance Menemukan 7 byter
Oliver

2

sed, 64 byte

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

Tentu, kita bisa menggunakan .alih-alih [[:alpha:]], tetapi sebenarnya harus [^ ], yang menguranginya menjadi 43, tetapi istirahat pada tanda baca dan semacamnya. Menggunakan [a-zA-Z]membawanya hingga 55, pada titik mana saya hanya mendambakan entitas yang dapat dibaca manusia yang manis dan manis ...
Rich

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.Dengan kata lain, Anda tidak perlu khawatir tentang tanda baca "melanggar" kode Anda dan bisa dengan aman pergi [^ ];)
Value Ink

@ ValueInk Ya, tapi [^ ]harus [^[:space:]]yang membawanya menjadi 67 karakter.
Kaya

"pembatas" berarti Anda dapat memastikan bahwa pembatas selalu merupakan ruang reguler. Siapa yang menggunakan tab dalam kalimat?
Nilai Tinta

Baik. Sepertinya "golf kode" adalah gim di mana Anda seharusnya menemukan cara untuk mendapatkan drone untuk menjatuhkan bola ke dalam lubang alih-alih benar-benar melakukan pekerjaan. Terima kasih atas sambutannya yang menyebalkan.
Kaya

2

sed , 34 byte

Dan mungkin ide pola akan bekerja dengan sebagian besar alat RE (dan saya tahu ada perbedaan antara RE standar dan RE diperpanjang).

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

Cobalah online!


1
Selamat datang di PPCG! Berpikir bahwa sifat serakah dari pertandingan regex berarti Anda dapat memotong \bdari pertandingan: Cobalah secara online!
Value Ink

Setuju @ValueInk - tapi saya akurat dengan pertandingan. Menghapus \bakan menyebabkan 30 byte.
PJF

Gunakan -E untuk regex tingkat lanjut dan Anda bisa menggunakan tanda kurung yang tidak terhapus. Gunakan .untuk karakter bertukar dan Anda bisa kehilangan dua karakter lainnya. Ini membawa Anda ke 26 byte; salah satu solusi terkecil yang bisa dibaca. s,\b(.)(\w*)(.)\b,\3\2\1,g
Kaya

1
- tidak, aku salah, kamu butuh huruf \ws di ujungnya. s,\b(\w)(\w*)(\w)\b,\3\2\1,g28 karakter.
Kaya

Kerja bagus @rich, tapi seperti yang saya katakan saya tahu tentang RE standar dan diperpanjang. Saya hanya memilih untuk menjadikannya standar dan mudah dibaca. Jangkar akan diminta yang saya lupa sebutkan dalam balasan saya ke ValueInk.
PJF

2

Ruby, 53 byte

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

Saya mencobanya tanpa regex. Keluaran mencetak setiap kata pada baris baru. Jika itu melanggar aturan, beri tahu saya dan saya akan memperbaikinya.

Tidak Terkumpul:

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

Selamat datang di PPCG! Mencetak setiap kata pada baris baru seharusnya baik-baik saja, tetapi solusi lama Anda ptidak bagus karena itu menambahkan kutipan ke output. Anda selalu dapat menggunakan putssebagai gantinya karena yang satu otomatis menambahkan baris baru dan lebih pendek dari print! Juga, jika Anda menelepon splittanpa argumen maka secara otomatis terbagi spasi.
Value Ink

2

8088 Majelis, IBM PC DOS, 39 38 byte

$ 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

Belum dirakit:

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 

Standalone PC DOS dapat dieksekusi. Input melalui args baris perintah, output ke layar.

masukkan deskripsi gambar di sini

Unduh dan uji PWAS.COM .



1

Batch, 141 byte

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

Mengambil input sebagai parameter baris perintah. Manipulasi string sangat buruk di Batch, dan keharusan untuk huruf tunggal kata tunggal tidak membantu.




1

Java, 110 109 byte

-1 byte dengan menggunakan baris baru untuk delimeter

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


Apakah ini berfungsi untuk kata-kata satu huruf?
Neil

@Neil tidak karena saya buruk. Saya akan memperbaikinya nanti.
Benjamin Urquhart

109 dengan menggunakan baris baru sebagai pembatas
Perwujudan Ketidaktahuan

1

Haskell , 75 74 byte

Memperbaiki bug yang ditunjukkan oleh Cubic dan juga menurunkan 1 byte.

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

Cobalah online!


map glebih pendek dari(g<$>)
Cubic

1
Juga, jika Anda melihat test case Anda, Anda akan melihatnya tidak bekerja untuk satu kata kata, itu berubah amenjadiaa
Cubic

1

Scala, 100 byte

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

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

Input adalah melalui tabel t yang sudah ada sebelumnya dengan bidang varchar v , sesuai standar IO kami .

Membaca dari belakang ke depan, STRING_SPLITmemecah string menjadi baris individual melalui pembatas, STUFFmemodifikasi karakter pada posisi yang ditentukan, lalu STRING_AGGmenggabungkannya kembali.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.