Apakah string ini surat yang melakukan gerakan jungkir balik?


35

Inspirasi tantangan adalah ini yang saya lihat di suatu tempat:

Kata "biarawati" hanyalah huruf dan melakukan gerakan jungkir balik

Tantangan Anda adalah mengambil seutas tali dan menentukan apakah itu huruf pertama yang melakukan gerakan jungkir balik.

Aturan

String adalah huruf yang melakukan gerakan jungkir balik jika:

  • Huruf pertama sama dengan huruf terakhir. (Surat itu tidak bisa mendarat di kepalanya.)
  • String berganti-ganti antara huruf cartwheeling setiap satu karakter.

Huruf cartwheeling adalah ndan u, mdan w, bdan q. Perhatikan bahwa ndan wbersama-sama bukan huruf cartwheeling, dan juga tidak wdan b.

  • Anda akan mengambil string menggunakan metode input standar kami.
  • Anda akan menampilkan nilai kebenaran jika string tersebut adalah huruf cartwheeling, dan nilai falsy jika bukan. Keluaran dapat dilakukan dengan menggunakan metode keluaran standar apa pun.

Aturan tambahan:

  • Hanya huruf kecil cartwheel n/ u/ m/ w/ b/ yang qperlu ditangani.
  • Anda dapat berasumsi bahwa input tidak pernah kosong.
  • String satu karakter bukan cartwheel yang valid.

Uji kasus

Input        -> Output
nun          -> truthy
nunun        -> truthy
nunununu     -> falsy
wmw          -> truthy
wmwun        -> falsy
bqbqbqbqbqb  -> truthy
v^v^v        -> falsy
AVAVA        -> falsy
OOO          -> falsy
ununununu    -> truthy
nunwmwnun    -> falsy
nun unun     -> falsy
nunwmw       -> falsy
nnuunnuunnuu -> falsy
nwnwnwnwn    -> falsy
m            -> falsy
nunuuunun    -> falsy

Pemenang

Seperti halnya , kode terpendek (dalam setiap bahasa) menang!


29
Saya pikir bjungkir balik ke dalam q, bukan? ddan pjuga teman-teman jungkir balik. Kuncinya adalah mereka berputar, bukan membalik.
Engineer Toast

Saran testcase lain:uwuwuwuwuwu
Kritixi Lithos

19
Kenapa bqbtapi tidak pdp?
aschepler

@aschepler saya mengacaukan.
MD XF

2
Karena dpd, pdp dan itu tidak berfungsi, saya pikir Anda harus memilikinya dalam kasus uji dengan jawaban yang salah.
trlkly

Jawaban:


2

Jelly , 23 byte

Ini membutuhkan lebih banyak pekerjaan daripada yang mungkin diperkirakan!

“nmbuwq”iЀo⁵IAs2⁼€3,3Ȧ

Tautan monadik yang mengambil daftar karakter dan kembali 1(benar) atau 0(falsey).

Cobalah online! atau lihat test suite .

Bagaimana?

Menemukan indeks setiap karakter input dalam daftar karakter 1-diindeks nmbuwq. String ini diatur sedemikian rupa sehingga indeks pasangan terpisah tiga, dengan demikian perbedaan tambahan dari indeks untuk roda-roda yang valid akan merupakan pengulangan salah satu [-3,3]atau [3,-3].

Ketika suatu item tidak ditemukan dalam daftar dengan indeks "atom", item iitu kembali 0, yang akan memasangkan karakter tidak berdasar dengan b, membuat input seperti benar bxbxb. Jadi 0, diganti dengan 10nilai lebih dari tiga dari nilai lain sebelum memeriksa validitas.

“nmbuwq”iЀo⁵IAs2⁼€3,3Ȧ - Link: list of characters, s
         Ѐ             - map across c in s:
        i               -   first index of c in (1-indexed; 0 if not present)
“nmbuwq”                -   literal "nmbuwq"
            ⁵           - literal 10
           o            - logical or (vectorises - replace any 0s with 10s)
             I          - incremental differences (i.e. deltas)
              A         - absolute value (vectorises)
               s2       - split into chunks of 2 (possibly with a single remainder)
                   3,3  - pair three with three = [3,3]
                 ⁼€     - equals? for €ach (1 if so, otherwise 0 - including a single 3)
                      Ȧ - any and all? (0 if any 0s or if empty, 1 otherwise)

13

sed 4.2.2 , 30 + 1 -r= 43 31 byte

Disimpan 12 byte berkat @Neil dengan memperpendek baris pertama

/nu|wm|qb/!d
/^((.).)\1*\2$/!d

Cobalah online!

Menghapus input jika falsey, jika tidak melakukan apa-apa pada input.

Penjelasan

Dengan -rflag, kita tidak perlu menggunakan \(dan \)untuk menangkap grup dan ini menghemat byte.

/nu|wm|qb/!                # On every line that does not match this regex
           d               # Delete
/^((.).)\1*\2$/!           # On every line that does not math
 ^((.).)                   #  the first two characters at the beginning of the line
        \1*                #  repeated
           \2$             #  with the first character at the end of the line
                d          # Delete

Ini dia sang sedpenyihir ...
MD XF

@ MDXF Saya jauh dari penyihir, masih pemula :)
Kritixi Lithos

Semuanya sedterlihat seperti sihir bagiku. : P
MD XF

1
Anda hanya perlu memeriksa isi setengah dari pasangan surat misalnya keduanya unudan nunmengandung nudan baris kedua memastikan bahwa sisa surat cocok dengan kedua.
Neil

8

JavaScript (ES6), 82 78 77 byte

Disimpan 1 byte dengan menggunakan dua nilai palsu, seperti yang disarankan oleh ThePirateBay dan MD XF.

([c,...s],S='bqwmun')=>s.reduceRight((r,a)=>r&a==S[S.search(c)^++k&1],k=s>'')

Uji kasus


Ada alasan untuk pergi, &&bukan &?

@ThePirateBay Yah, satu-satunya alasan adalah konsistensi nilai falsy yang dikembalikan, meskipun tampaknya tidak benar-benar menjadi persyaratan untuk tantangan ini. (Menggunakan &akan menghasilkan salah satu falseatau 0.)
Arnauld

@Arnauld Anda dapat menghapus yang kedua &; Saya menentukan (dalam obrolan) kadang-kadang bahwa nilai falsy yang tidak konsisten diizinkan.
MD XF

5

Python 3 , 111 byte

-2 byte terima kasih kepada Tn. Xcoder.

lambda s:s[0]==s[-1]and any(any({*s[::2]}=={i[j]}and{*s[1::2]}=={i[j<1]}for j in[0,1])for i in['nu','mw','bq'])

Cobalah online!


2
mendesah saat Anda menyerahkan saya dalam perwakilan lagi
MD XF

Saya tidak merasa nyaman dengan ini, karena Anda akan mencapai jumlah byte saya lagi, tetapi -2 byte .
Tn. Xcoder

BTW, solusi Anda tidak valid, seperti milik saya di awal. Gagal untuk nunununu.
Tn. Xcoder

Diperbaiki dengan biaya banyak byte. ; -;
totallyhuman

5

Python 2 , 63 byte

lambda s:s[:3]in'ununqbqbwmwm'and s==s[:2]*max(len(s)/2,1)+s[0]

Cobalah online!


Jawaban yang bagus, selamat datang di situs ini! Beberapa tips: Anda bisa lakukan "nu un nm mn bp pb".split()untuk menghemat 4 byte, dan Anda bisa menghapus spasi. 75 byte:lambda s:any(s==c[-1]+c*max(len(s)/2,1)for c in"nu un nm mn bp pb".split())
DJMcMayhem

Anda dapat menghemat 1 byte dengan melakukan s[0]alih - alih c[-1].
DJMcMayhem

Jawaban 61 byte mengembalikan Benar untuk unmnudan unmwnu. Benar-benar mengembalikan positif palsu ketika (s==s[::-1])+len(set(s))4, yang mudah dipaksakan. Bahkan hanya 4 karakter yang berbeda membuatnya kembali Benar.
Arnold Palmer

The 59 byte istirahat dengan input karakter tunggal. Maaf untuk memilih yang ini, saya suka Python :)
Arnold Palmer

Bukankah pengecualian itu palsu? Istirahat itu disengaja
Harrichael

5

Python 3 , 71 byte

lambda n:''.join(sorted({*n[1::2]}|{*n[::2]}))in"nu,mw,bq"*(n==n[::-1])

Cobalah online!

-1 berkat @HyperNeutrino dan -13 terima kasih kepada @ovs

Jika di atas ditemukan gagal untuk setiap kasus uji, ada alternatif:

lambda n:(sorted(list({*n[1::2]}.union({*n[::2]})))in[[*'nu'],[*'mw'],[*'bq']])*n[0]==n[-1]

Cobalah online!


Penjelasan

  • ''.join(sorted(list({*n[1::2]}).union({*n[::2]})))) - Mendapat karakter pada indeks ganjil dan karakter pada indeks genap, menduplikasi mereka dan mengurutkan daftar yang dibentuk oleh penyatuan mereka.

  • in'nu,mw,bq' - Memeriksa apakah kombinasi surat-surat yang valid.

  • n[0]==n[-1] - Memeriksa apakah karakter pertama sama dengan yang terakhir.


Gagal tidak ada kasus pengujian, pekerjaan yang baik +1
MD XF

@ MDXF Oh terima kasih! Saya sangat lega ...> _ <
Mr. Xcoder

1
uwuwuwuwuwumenghasilkan true
Kritixi Lithos

1
Valid: nunuuunun
Harrichael

1
nuuun -> True. Ini tidak benar.
rekursif

5

JavaScript (ES6), 40 byte

s=>/^(nu|un|bq|qb|wm|mw)+$/.test(s+s[1])

Cek untuk melihat apakah string input digabungkan dengan karakter kedua dari string input adalah string berulang dari pasangan karakter cartwheel yang sama.

Tes:

[
  "nun",
  "nunun",
  "nunununu",
  "wmw",
  "wmwun",
  "bqbqbqbqbqb",
  "v^v^v",
  "AVAVA",
  "OOO",
  "ununununu",
  "nunwmwnun",
  "nun unun",
  "nunwmw",
  "nnuunnuunnuu",
  "nwnwnwnwn",
  "m",
  "nunuuunun"
].forEach( x=>console.log( x, (s=>/^(nu|un|bq|qb|wm|mw)+$/.test(s+s[1]))(x) ) )


Sangat suka logikanya di sini! Saya tidak akan pernah berpikir untuk menambahkan karakter di akhir dan pengujian. Bagus, kode bersih, juga, bahkan ketika bermain golf.
trlkly

4

Clojure, 156 byte

(fn[w](let[s["nu""wm""bq"]c #(= 1(count(set %)))e #(take-nth 2 %)r #(and(c(e %))(c(e(drop 1 %))))](and(=(first w)(last w))(r w)(some #(=(set w)(set %))s))))

Ini ternyata sulit! Saya akhirnya harus memecahnya menjadi 3 sub masalah:

  • Apakah huruf pertama sama dengan yang terakhir?
  • Apakah surat-surat itu diulang?
  • Apakah semua huruf merupakan bagian dari salah satu set yang valid?

Saya tentu saja tidak menang, tetapi ini adalah latihan pagi yang baik! Penjelasan lengkap di bawah ini:

(defn cartwheel? [word]
  (let [; Valid Character Sets
        cs ["nu" "wm" "bq"]

        ; Is the list composed of only a single character?
        count-1? #(= 1 (count (set %)))

        ; Grabs every other element of the list
        every-other #(take-nth 2 %)

        ; Do the characters repeat? Works by checking if every other element is the same, then drops the first letter
        ; to check all the odd indexed characters
        repeating? #(and (count-1? (every-other %))
                         (count-1? (every-other (drop 1 %))))]

    ; Do all the predicates hold?
    (and (= (first word) (last word))
         (repeating? word)
         ; Is the set of letters in the word part of some set of the valid characters?
         (some #(= (set word) (set %)) cs))))

4

Haskell, 80 78 byte

f s|l<-length s=odd l&&l>1&&any((==s).take l.cycle)(words"un nu mw wm bq qb")

Cobalah online!

Bagaimana itu bekerja:

l<-length s        -- let l be the length of the input string

f s         =      -- return True, if
    odd l          -- l is odd and
    l > 1          -- l is greater than 1 and 
    any            -- any of the following is also True
      (     )(words "  ...  ")
                   -- apply the function to each of the words "un", "nu" ... "qb"
           cycle   --  infinitely repeat the word
      take l       --  take the first l characters
     (==s)         --  and compare to s

4

Python 2 , 45 byte

lambda s:s[2:]+s[1:3]==s>s[:2]in'bqbunuwmw'

Cobalah online!

Spasi dalam string adalah DELkarakter.


|u|ditafsirkan sebagai roda jungkir balik.
Harrichael

@ Harrichael saya memasukkan DELkarakter menjadi jelas.
xnor

Karakter DEL masih bisa menjadi karakter input. Saya suka solusi Anda, tetapi Anda harus meminjam trik dari jawaban saya:s[:3]in'bqbqnunuwmwm'
Harrichael

4

Retina , 24 byte

G`nu|mw|bq
^((.).)\1*\2$

Output 1 untuk truey, 0 untuk falsy.

Jawaban Port of Quack tentang dukun.

Cobalah online!


Versi yang lebih baru menampilkan kebenaran untuk nunwmwnun(ketika itu harus salah), itulah sebabnya saya memiliki \1*jawaban sed saya.
Kritixi Lithos

@Cowsquack Ah saya mengerti.
Okx

Baris pertama bisa jadi G`nu|mw|bpkarena semua string yang benar mengandung salah satu pasangan surat itu dan baris kedua akan memastikan bahwa semua string lainnya mengandung huruf-huruf itu juga ..
Neil

@ Neil Itu gagal test caseununununu
Okx

Saran @Okx Neil tampaknya masih berfungsi untuk testcase itu Coba online!
Kritixi Lithos

3

Grime , 28 byte

e`..-#!"nu\|bq\|mw"oTv&..v+.

Cobalah online! Mencetak 1untuk input yang benar dan 0yang salah.

Penjelasan

Sintaksis Grime menyerupai ekspresi reguler, dan program Grime menentukan pola yang mungkin cocok atau tidak cocok dengan persegi panjang karakter.

e`..-#!"nu\|bq\|mw"oTv&..v+.
e`                            Match input against pattern:
      !                       Does not
     #                        contain
  ..                          a 2-character substring
    -                         which is not
       "nu\|bq\|mw"           any of these strings
                   oT         potentially reversed,
                     v&       AND
                       ..     two characters
                         v+   one or more times
                           .  then one more character.

Beberapa fitur Grime yang membantu mempersingkat ini:

  • Biasanya literal karakter harus diloloskan dengan backslash, tetapi ""ubahlah ini: elemen sintaksis diloloskan tetapi literal tidak. Tanpa tanda kutip, bagian yang menyebutkan pasangan karakter akan menjadi (\n\u|\b\p|\m\w)oT.
  • Operator unary yang mengikuti operator biner (di sini -) bertindak atas hasilnya: ..-#!"…"oTsama dengan (..-"…"oT)#!.
  • Semakin vrendah prioritas elemen sintaksis yang mengikutinya. Seseorang &memiliki prioritas lebih tinggi daripada -, tetapi v&memiliki lebih rendah. Demikian pula, ..+diuraikan sebagai .(.+), tetapi ..v+setara dengan (..)+.


2

Pyth , 27 byte

&qeQhQ/"nu,mw,bq"S+{%2tQ{%2

Test Suite.

Keluaran 1untuk kebenaran dan Falseatau 0untuk kepalsuan, karena OP diizinkan dalam obrolan.


2

Jelly , 27 byte

Ḋm2Qµ³m2Q;Ṣe“nu“mw“bq”ȧ³⁼U¤

Cobalah online!

Bagaimana itu bekerja

Ḋm2Qµ³m2Q;µṢe“nu“mw“bq”ȧ³⁼U¤  Main link; z is the argument
Ḋ                             z[1:]
 m2                           z[1::2]
   Q                          deduplicate(z[1::2])
    µ                         New Chain
     ³                        z
      m2                      z[::2]
        Q                     deduplicate(z[::2])
         ;                    deduplicate(z[1::2]) + deduplicate(z[::2])
          Ṣ                  Sort the result
           e                 Is it an element of the following?
            “nu“mw“bq”       ["nu", "mw", "bq"]
                      ȧ      It has the correct characters and:
                       ³  ¤  Nilad followed by links as nilad
                       ³     z
                        ⁼      == 
                         U        z[::-1]
                          ¤  [End chain]

Jelly ... lebih lama dari Pyth ?!
Tn. Xcoder

@ Mr.Xcoder shhhh Saya sedang mengerjakannya ... xD
HyperNeutrino

Hah, saya terikat dengan Anda sekarang xD
HyperNeutrino



1

Python 3 , 88 byte

lambda x:[len(x)%2,x[:2]in'nu,un,bq,qb,mw,wm',len(set(x[::2])),len(set(x[1::2]))]==[1]*4

len(x)%2: string genap tidak dapat berakhir pada karakter pertama

x[:2] in: periksa salah satu dari 6 pasangan awal yang valid

len(set()): dapatkan panjang kumpulan karakter di 0,2,4 ... dan 1,3,5 ...

Kembali Truejika daftar evaluasi sama dengan [1,1,1,1], yang lain False.

Cobalah online!


1

Perl 5 , 55 + 1 (-p) = 56 byte

$c={"nuunmwwmbppb"=~/./g}->{$l=chop};$_=/^($l$c)+$/&&$c

Cobalah online!

Mencetak versi "terbalik" dari karakter pertama untuk true, nothing for false.


Kalahkan saya dengan 18 byte solid. Jawaban bagus!
Silvio Mayolo

Tidak banyak sekarang. Dokumen asli dikembalikan benar untuk string apa pun dari semua karakter yang sama.
Xcali

1

PHP, 59 +1 byte

<?=preg_match('#^(nu|un|mw|wm|bq|qb)\1+$#',$argn.$argn[1]);

Jalankan sebagai pipa dengan -F .

sebagian solusi regex, 101 +1 byte:

for($s=$argn;$c=$s[$i++];$p=$c)$c!=$p||die;echo$i%2<1&&preg_match("#^(nu|mw|bq)#",count_chars($s,3));

Output kosong untuk falsy. Jalankan sebagai pipa dengan -nR.


1

Java 8, 57 byte

s->s.matches("(nu)+n|(un)+u|(mw)+m|(wm)+w|(bq)+b|(qb)+q")

Coba di sini.

Regex sederhana untuk mencocokkan semua enam kasus. Perhatikan bahwa Java String#matchessecara otomatis cocok dengan seluruh String, jadi tidak perlu ^...$.


1

MATL , 25 byte

'nuwmbq'&mq2&\d~wdts~Gnqv

Ouput adalah vektor kolom numerik yang tidak kosong, yang truthy jika semua entri yang adalah nol, dan falsy sebaliknya. Cobalah online!

Untuk memverifikasi semua kasus uji , ifcabang ditambahkan di footer yang menggantikan nilai kebenaran dengan string 'truthy', atau nilai falsy dengan string 'falsy', dan kemudian menampilkan string.

Penjelasan

'nuwmbq'  % Push this string
&m        % Implicit input. For each char, push index of membership in the above
          %  string, or 0 if not member
q         % Subtract 1
2         % Push 2
&\        % Divmod. Pushes remainders, then quotients
d~        % Consecutive differences negated. Gives an array of ones iff all
          % quotients were equal
w         % Swap. Moves remainders to top
d         % Consecutive differences. Gives nonzeros iff no consecutive
          % remainders were equal
ts~       % Duplicate, sum, negate. Gives true iff sum was 0. For unequal
          % consecutive differences of remainders, this corresponds to an odd
          % number of remainders
Gnq       % Push input, length, subtract 1. True iff input longer than 1
v         % Concatenate into column vector. Truthy iff all entries are nonzero


0

Clojure, 115 byte

(apply some-fn(map(fn[r]#(re-matches r %))(map(fn[[x y]](re-pattern(str x"("y x")+")))["nu""un""mw""wm""bq""qb"])))

Buat regex dari setiap pasangan surat dan lihat apakah inputnya cocok. Banyak cara yang lebih elegan untuk melakukan semua bagian ini, tetapi semuanya lebih bertele-tele. Begitulah hidup dengan bermain golf Clojure.


0

Perl 5, 68 + 1 = 69 byte

if(/../&&$&=~/nu|un|bq|qb|mw|wm/){s/^($&)*//;$&=~/./;print if/^$&$/}

Jalankan dengan -n.

Penjelasan:

# Match the first two characters, and if they exist, then...
if (/../ &&
 # Make sure they are a pair of compatible cartwheel characters.
 $&=~/nu|un|bq|qb|mw|wm/) {
  # If that's true, then eliminate as many of that pair of characters
  # from the beginning of the string as possible.
  s/^($&)*//;
  # Then get the first character out of the match (the first character
  # of the original string).
  $&=~/./;
  # Print the text (which is truthy since it's nonempty) if the original
  # first character matches exactly the remaining string.
  print if/^$&$/
  # Otherwise, print nothing (the empty string in Perl is falsy).
}

0

TXR Lisp , 50 byte

(f^$ #/n(un)+|u(nu)+|m(wm)+|w(mw+)|b(qb)+|q(bq)+/)

Menjalankan:

1> (f^$ #/n(un)+|u(nu)+|m(wm)+|w(mw+)|b(qb)+|q(bq)+/)
#<intrinsic fun: 1 param>
2> [*1 "nun"]
"nun"
3> [*1 "nuns"]
nil
4> [*1 "mwm"]
"mwm"
5> [*1 "wmw"]
"wmw"
6> [*1 "abc"]
nil

f^$adalah kombinator yang mengambil objek regex dan mengembalikan fungsi yang cocok dengan regex itu dengan cara berlabuh. (Dengan sendirinya, objek regex adalah objek yang dapat dipanggil fungsi yang mengambil string dan mencari sendiri melalui itu.)



0

TXR : 78 74 byte

@{x 2}@(rep :gap 0)@x@(end)@y
@(bind(x y)(#"nu un mw wm bq qb"@[x 0..1]))

Jalankan, dari prompt sistem. Nomor prompt adalah status penghentian: 0 = sukses, 1 = gagal:

0:$ ./txr cart.txr 
nun
0:$ ./txr cart.txr 
abc
1:$ ./txr cart.txr 
bab
1:$ ./txr cart.txr 
mwm
1:$ ./txr cart.txr 
nununununun
0:$

Penjelasan:

  • @{x 2}: cocokkan dua karakter, ikat ke xvariabel.
  • @(rep :gap 0)@x@(end): pertandingan berulang tanpa celah yang dilewati: nol atau lebih dari x, digraf yang sebelumnya cocok.
  • @y: sisa garis cocok, ditangkap y.
  • @(bind(x y)(foo bar)): ikat xke foo, y ke bar. Karena xdan ysudah terikat, mereka harus cocok foodan bar, atau ada kegagalan.
  • fooadalah #"nu un mw wm bq qb", daftar kata harfiah, gula sintaksis untuk daftar Lisp ("nu" "un" ... "qb"). Sebuah bindpertandingan antara variabel dan daftar berarti bahwa variabel harus sesuai elemen.
  • baradalah @[x 0..1]: substring satu karakter xdari awal. The bindpertandingan antara ydan pasukan ini huruf terakhir dari garis untuk mencocokkan pertama.

0

C ++, 268 byte

#include<map>
#include<string>
std::map<char,char>c{{'n','u'},{'m','w'},{98,'q'},{'w','m'},{'u','n'},{'q',98}};
int w(std::string s){if(s[0]!=s[s.size()-1]||c.find(s[0])==c.end()||s.size()<3)return 0;for(int i=0;i<s.size()-1;i+=2)if(s[i+1]!=c[s[i]])return 0;return 1;}

Simpan 10 byte dengan menggunakan nilai ASCII untuk semua karakter, bukan hanya dua.
MD XF

@MDXF n= 110, u= 117, m= 109, w= 119, q= 113. Jadi, menggunakan nilai ASCII atau tidak tidak masalah untuk karakter yang lebih tinggi dari c(99)
HatsuPointerKun

0

JavaScript (ES6), 63 byte

s=>/bq|wm|un/.test(s)&s.replace(RegExp(s[0]+s[1],'g'),'')==s[0]

Pengembalian 1atau 0.

Penjelasan

Semua string roda gila akan memiliki satu atau lebih bq , wm , atau un . Kami menguji dengan:

/bq|wm|un/.test(s)

Jika Anda mengganti semua contoh dari dua huruf pertama dari string roda gila dengan apa-apa, Anda memiliki huruf pertama dari string tersebut. Kami menguji dengan:

s.replace(RegExp(s[0]+s[1],'g'),'')==s[0]

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.