Buat teks pelangi

22

Tantangan Anda adalah mengambil input sebagai garis teks dan menampilkannya seperti ini.

gambar pelangi

Input output

Input akan berupa string yang hanya berisi karakter ASCII yang dapat dicetak. Karakter pertama atau terakhir tidak akan pernah menjadi spasi, dan tidak akan pernah ada dua spasi dalam satu baris. Panjangnya akan selalu setidaknya dua karakter.

Output Anda harus string yang sama, dikonversi ke warna pelangi seperti yang akan dijelaskan di bawah ini. Outputnya mungkin dalam bentuk gambar (disimpan ke file atau entah bagaimana dibuat tersedia), atau mungkin hanya menampilkan hasilnya di layar (seperti implementasi referensi di bawah ini).

Konversi

Untuk menentukan apa warna setiap huruf dalam string seharusnya, gunakan algoritma berikut. Perhatikan bahwa setiap huruf adalah warna masing-masing . Ini bukan gradien!

  • Jika karakter ini adalah spasi:

    • ... tidak masalah, karena ruang tidak bisa benar-benar ... memiliki warna. Cukup output ruang.
  • Jika tidak:

    • Misalkan i= indeks karakter ini dalam string (berbasis 0, jadi untuk huruf pertama, ini 0), tidak menghitung spasi. Misalnya, dalam string foo bar, nilai ini adalah 4untuk a. Dengan kata lain, sejauh ini sudah berapa banyak ruang kosong yang ditemukan.

    • Let n= jumlah non-spasi dalam string.

    • Warna surat ini sekarang dapat dinyatakan, dalam sistem koordinat-silindris HSL , sebagai [rona = ( i/ n) * 360 °, saturasi = 100%, cahaya = 50%].

Perhatikan bahwa arah ini menyiratkan bahwa output untuk foodan f ooharus persis sama, kecuali untuk ruang tambahan setelah f. Artinya, semua huruf harus mempertahankan warna yang sama.

Aturan lebih lanjut untuk proses konversi dijelaskan di bawah ini, di bagian Aturan .

Implementasi referensi

Ini ditulis dalam JavaScript, dan Anda dapat mencobanya dengan menekan tombol "Run snippet".

window.addEventListener('load', function() {
    addRainbow('Your challenge is to take input as a line of text and ' +
        'output it like this.');
});

// append this text rainbow-ified to the argument (document.body by default)
function addRainbow(text, el) {
    (el || document.body).appendChild(makeRainbow(text));
}

// returns a <div> that contains the text in a rainbow font
function makeRainbow(text) {
    var div = document.createElement('div');
    var letterCount = text.replace(/ /g, '').length, spaceCount = 0;
    text.split('').forEach(function(letter, idx) {
        if (letter == ' ') ++spaceCount;
        div.appendChild(makeLetter(letter, (idx - spaceCount) / letterCount));
    });
    return div;
}

// returns a <span> that contains the letter in the specified color
function makeLetter(letter, hue) {
    hue = Math.floor(hue * 360);
    var span = document.createElement('span');
    span.appendChild(document.createTextNode(letter));
    span.style.color = 'hsl(' + hue + ', 100%, 50%)';
    return span;
}

Aturan

  • Saat menghitung nilai Hue dari sebuah huruf, Anda hampir pasti akan mendapatkan angka desimal (non-integer). Anda bisa membulatkan ini ke bilangan bulat terdekat, melantai, mengambil langit-langit, atau tidak bulat sama sekali.

  • Ukuran font harus dapat dibaca. Di sini, ini didefinisikan sebagai font ukuran 10pt atau lebih besar.

  • Anda dapat menggunakan kanvas dengan lebar tetap atau "area gambar" untuk menampilkan teks, tetapi harus dapat mencocokkan dengan contoh yang diberikan pada kalimat pertama posting ini.

  • Skor adalah , sehingga kode terpendek dalam byte akan menang.

Gagang pintu
sumber
Bisakah output menjadi Data URI? Itulah output dari kanvas HTML
Downgoat
@vihan Ya, yang memenuhi syarat sesuai dengan " Output mungkin dalam bentuk gambar (disimpan ke file atau entah bagaimana disediakan) " aturan.
Gagang pintu
Bagaimana Anda menentukan apakah suatu warna memenuhi spesifikasi? Bisakah Anda menentukan dengan tepat rumus konversi apa yang harus digunakan jika hanya warna RGB yang didukung dalam bahasa? Juga, berapa banyak bit presisi per saluran yang diperlukan? Agaknya 8 akan baik-baik saja, tetapi bagaimana dengan 4, atau 1?
feersum
@feersum Untuk mengkonversi ke RGB, Anda dapat menggunakan builtin atau salah satu metode yang dijelaskan di sini . Bisakah Anda mengklarifikasi apa yang Anda maksud dengan pertanyaan kedua? Apakah Anda bertanya tentang hal ini secara khusus dalam konteks konversi HSL ke RGB, atau secara umum?
Gagang pintu
2
Sial, saya bahkan tidak akan mencoba dengan PowerShell ... Anda hanya mendapatkan 16 warna untuk dimainkan (dan mereka bahkan tidak dipesan ... pelangi atau RGB atau sebaliknya ... hanya nilai hex sewenang-wenang). Referensi, dengan Gambar , Tantangan yang sangat keren!
AdmBorkBork

Jawaban:

12

Perl, 95

92 byte kode + 3 untuk -p

Skrip ini menggunakan perkiraan warna yang tersedia untuk terminal (maksimum 256) saat ini hanya termasuk beberapa titik warna yang dipilih dari daftar ini , jadi kemungkinan besar tidak akan ditentukan, tetapi ini tetap menyenangkan! Saya memfilter daftar untuk hanya menampilkan warna dengan Sdan Lnilai 100%dan50% masing masing, lalu diurutkan berdasarkan rona, mengemas angka-angka ke dalam string dan memilih warna dari daftar itu.

Implementasi ini termasuk karakter yang tidak dapat dicetak! Gagasan mencuri @ edc65 hanya mengganti \Sbukan ., sederhana, tapi pintar!

@c=map ord,"..........vR../012.3-'!..9]........"=~/./g;s|\S|\e[38;5;$c[@c*$i++/y/!-~//]m$&|g

Hexdump:

0000000: 4063 3d6d 6170 206f 7264 2c22 09c4 cad0  @c=map ord,"....
0000010: d6dc 0be2 be9a 7652 0a2e 2f30 3132 0e33  ......vR../012.3
0000020: 2d27 211b 1539 5d81 a50d c9c8 c7c6 c522  -'!..9]........"
0000030: 3d7e 2f2e 2f67 3b73 7c5c 537c 5c65 5b33  =~/./g;s|\S|\e[3
0000040: 383b 353b 2463 5b40 632a 2469 2b2b 2f79  8;5;$c[@c*$i++/y
0000050: 2f21 2d7e 2f2f 5d6d 2426 7c67            /!-~//]m$&|g

Balikkan hexdump dengan menyalin teks di atas dan menjalankan:

xxd -r > rainbowtext.pl

menempelkan data dan menekan Ctrl+D .

Jalankan menggunakan:

perl -p rainbowtext.pl <<< 'Your challenge is to take input as a line of text and output it like this.'

Ini menghasilkan output seperti:

SEKARANG TEKS TERMINAL ANDA MERAH!  MUHAHAHAHA!

Dom Hastings
sumber
10

Python 2: 240 menggunakan PIL dan colorsys lib

import PIL,colorsys as c
s=input()
u,a=len(s),255
g=Image.new('RGB',(u*6,13),(a,)*3)
[ImageDraw.Draw(g).text((j*6,0),s[j],fill=tuple(int(h*a)for h in c.hls_to_rgb(1.*(j-s[:j].count(' '))/(u-s.count(' ')),.5,1)))for j in range(u)]
g.show()

Contoh output:

Keluarkan contoh teks pelangi uji dengan spasi

Terima kasih kepada @agtoever dan @Trang Oul untuk beberapa kiat bermain golf, dan untuk @Mauris untuk menunjukkan persyaratan ruang.

Untuk menambahkan font jenis sebenarnya, kontrol ukuran font, termasuk offset horizontal dan perubahan warna berdasarkan panjangnya.

import PIL as P,colorsys as c
s=input()
u=len(s)
a=255
fs=25
f=P.ImageFont.truetype("a.ttf",fs)
sza=f.getsize(s)
oa=f.getoffset(s)
g=P.Image.new('RGB',(sza[0]+fs,2*sza[1]+oa[1]),(a,)*3)
r=fs/4
P.ImageDraw.Draw(g).text((r,0),s,fill=(0,0,0),font=f)
for j in range(u):   
 o=f.getoffset(s[j])
 sz=f.getsize(s[j])   
 r+=o[0]
 P.ImageDraw.Draw(g).text((r,0+fs),s[j],fill=tuple([int(h*a)for h in c.hls_to_rgb(1.*r/sza[0],.5,1)]),font=f)
 r+=sz[0]
g.save('a.png')
g.show()

Font yang saya gunakan tersedia dari sini : Hasilnya (bagian atas hanya mencetak string, yang di bawah ini mencetak per huruf):

mesin tik

Willem
sumber
1
Jatuhkan as Pdan tulis PILdua kali dan menangkan satu karakter. Ubah imgke idan menangkan 4 karakter lainnya.
agtoever
1
Simpan 255ke variabel, ganti semua ocurrences dan gunakan (a,)*3sebagai warna putih. Ganti float(j)dengan (j+.0).
Trang Oul
1
Juga: ganti float(j)ke1.*j
agtoever
1
Tetapkan beberapa variabel secara bersamaan (mis. u=len(s) a=255=> u,a=len(s),255). Hapus []tanda kurung dari tuple, mereka tidak diperlukan. Ganti loop dengan daftar pemahaman (metode akan dievaluasi sebagai efek samping).
Trang Oul
1
@willem: Lihatlah spesifikasi masalah (di bawah Konversi ); itu secara khusus menjelaskan bagaimana program Anda harus menangani spasi.
Lynn
5

JavaScript (ES6), 114 117 125

Edit2 3 byte disimpan thx @Dom Hastings Edit HTML tidak valid, tetapi tetap bekerja.

Catatan biasa: tes menjalankan cuplikan pada browser yang sesuai EcmaScript 6 (terutama bukan Chrome bukan MSIE. Saya menguji pada Firefox)

F=s=>document.write(s.replace(/\S/g,c=>`<b style=color:hsl(${i++/s.replace(/ /g,'').length*360},100%,50%>`+c,i=0))
<input value='Your challenge is to take input as a line of text and output it like this.' id=I size=100>
<button onclick='F(I.value)'>-></button>

edc65
sumber
1
Belum ada browser yang sepenuhnya sesuai dengan ES6. IE bahkan belum sepenuhnya memenuhi standar ES5!
SuperJedi224
@ SuperJedi224 Saya setuju. Saya hanya mengatakan: jangan coba-coba dengan Chrome atau MSIE, saat menggunakan Firefox berfungsi
edc65
Saya merasa seolah-olah saya seharusnya tidak mengatakan apa-apa karena saya hanya punya milik saya di bawah milik Anda, tetapi saya pikir Anda dapat menghilangkan deklarasi )Anda hsl(karena tampaknya masih bekerja untuk saya di Firefox!
Dom Hastings
Juga, Anda dapat mengubah ${c}'untuk '+cmenyimpan 2 lagi ... Lebih baik kembali dengan milikku!
Dom Hastings
Ini tidak berfungsi di Safari 9.0. c:
Addison Crump
4

Python 3, 131 byte

Simular dengan jawaban Dom Hastings tetapi diimplementasikan dengan python.

String '|\x82\x88\x8ejF"#$%\x1f\x19\x137[\x7f~}'dibangun dari daftar[124,130,136,142,106,70,34,35,36,37,31,25,19,55,91,127,126,125] adalah kode warna terminal untuk ditampilkan secara berurutan. Mereka telah difilter sehingga mereka hanya menyertakan warna dengan saturasi 100% dan nilai 50%. Daftar itu kemudian disortir sehingga rona yang benar ditampilkan terlebih dahulu.

Mengambil input dari stdin dan mengembalikannya ke stdout.

Terminal Anda yang Anda gunakan HARUS mendukung kode pelarian ANSI untuk menjalankan ini dengan benar.

x=input();u=u'|\82\88\8ejF"#$%\1f\19\137[\7f~}';j=0
for i in x:print('\033[38;5;%dm%s'%(ord(u[j*18//len(x.replace(" ", ""))]),i),end="");j+=i!=" "

Atau versi singkat dengan karakter byte literal (Tidak menempel dengan benar):

x=input();u='|<82><88><8E>jF"#$%^_^Y^S7[^?~}';j=0
for i in x:print('ESC[38;5;%dm%s'%(ord(u[(j*18)//len(x.replace(" ", ""))]),i),end="");j+=i!=" "

Hexdump literal:

783d696e70757428293b753d277c82888e6a46222324251f1913375b7f7e7d273b6a3d300a666f72206920696e20783a7072696e7428271b5b33383b353b25646d25732725286f726428755b286a2a3138292f2f6c656e28782e7265706c616365282220222c20222229295d292c69292c656e643d2222293b6a2b3d69213d2220220a

Terima kasih @swstephe untuk menghemat 9 byte (dan juga membuat saya memperhatikan penghitungan byte saya sedikit salah)!

Biru
sumber
Mengapa tidak mengganti "\ x82" dengan karakter sebenarnya? Saya menulis string itu ke file dan membacanya kembali ke skrip saya dalam biner. Anda dapat mengganti \ 033 dengan karakter pelolosan mentah, atau bahkan \ 1f (hex). Anda mendeklarasikan "u", lalu hanya menggunakannya sekali. Anda dapat menyimpan beberapa karakter dengan memindahkannya ke ekspresi. Anda dapat menghindari panggilan int () dengan menggunakan "//" untuk pembagian integer.
swstephe
oops, \ 033 sama dengan \ x1f.
swstephe
2

PHP, 165 byte

Jalankan dengan input sebagai parameter "s"

HTML tidak valid tetapi harus dirender di semua browser utama (diuji di Chrome dan Firefox)

<?php $n=preg_match_all("/[^ ]/",$q=$_GET['s']);for($i=$j=0;$j<strlen($q);$j++){if(" "!=$s=$q[$j])$i+=360;echo"<a style='color:hsl(".floor($i/$n).",100%,50%)'>".$s;}
DankMemes
sumber
1

PHP 4.1, 112 103 102 byte

Saya sudah menggunakan jawaban @DankMemes sebagai titik awal. Dari sana, saya sudah menerapkan banyak perubahan, ke titik bahwa kode berbeda.

Implementasinya mirip, kodenya sama sekali berbeda.

foreach(str_split($s)as$c)echo"<a style=color:hsl(",((" "^$c?$i+=360:$i)/strlen($s))|0,",100%,50%>$c";

Untuk menggunakannya, cukup tetapkan nilai pada SESI / DAPATKAN / POST / COOKIE dengan nama s.

Hasil menjalankan fungsi ini, pada kalimat tes:

<a style=color:hsl(4,100%,50%>Y<a style=color:hsl(9,100%,50%>o<a style=color:hsl(14,100%,50%>u<a style=color:hsl(19,100%,50%>r<a style=color:hsl(24,100%,50%> <a style=color:hsl(29,100%,50%>c<a style=color:hsl(34,100%,50%>h<a style=color:hsl(38,100%,50%>a<a style=color:hsl(43,100%,50%>l<a style=color:hsl(48,100%,50%>l<a style=color:hsl(53,100%,50%>e<a style=color:hsl(58,100%,50%>n<a style=color:hsl(63,100%,50%>g<a style=color:hsl(68,100%,50%>e<a style=color:hsl(72,100%,50%> <a style=color:hsl(77,100%,50%>i<a style=color:hsl(82,100%,50%>s<a style=color:hsl(87,100%,50%> <a style=color:hsl(92,100%,50%>t<a style=color:hsl(97,100%,50%>o<a style=color:hsl(102,100%,50%> <a style=color:hsl(107,100%,50%>t<a style=color:hsl(111,100%,50%>a<a style=color:hsl(116,100%,50%>k<a style=color:hsl(121,100%,50%>e<a style=color:hsl(126,100%,50%> <a style=color:hsl(131,100%,50%>i<a style=color:hsl(136,100%,50%>n<a style=color:hsl(141,100%,50%>p<a style=color:hsl(145,100%,50%>u<a style=color:hsl(150,100%,50%>t<a style=color:hsl(155,100%,50%> <a style=color:hsl(160,100%,50%>a<a style=color:hsl(165,100%,50%>s<a style=color:hsl(170,100%,50%> <a style=color:hsl(175,100%,50%>a<a style=color:hsl(180,100%,50%> <a style=color:hsl(184,100%,50%>l<a style=color:hsl(189,100%,50%>i<a style=color:hsl(194,100%,50%>n<a style=color:hsl(199,100%,50%>e<a style=color:hsl(204,100%,50%> <a style=color:hsl(209,100%,50%>o<a style=color:hsl(214,100%,50%>f<a style=color:hsl(218,100%,50%> <a style=color:hsl(223,100%,50%>t<a style=color:hsl(228,100%,50%>e<a style=color:hsl(233,100%,50%>x<a style=color:hsl(238,100%,50%>t<a style=color:hsl(243,100%,50%> <a style=color:hsl(248,100%,50%>a<a style=color:hsl(252,100%,50%>n<a style=color:hsl(257,100%,50%>d<a style=color:hsl(262,100%,50%> <a style=color:hsl(267,100%,50%>o<a style=color:hsl(272,100%,50%>u<a style=color:hsl(277,100%,50%>t<a style=color:hsl(282,100%,50%>p<a style=color:hsl(287,100%,50%>u<a style=color:hsl(291,100%,50%>t<a style=color:hsl(296,100%,50%> <a style=color:hsl(301,100%,50%>i<a style=color:hsl(306,100%,50%>t<a style=color:hsl(311,100%,50%> <a style=color:hsl(316,100%,50%>l<a style=color:hsl(321,100%,50%>i<a style=color:hsl(325,100%,50%>k<a style=color:hsl(330,100%,50%>e<a style=color:hsl(335,100%,50%> <a style=color:hsl(340,100%,50%>t<a style=color:hsl(345,100%,50%>h<a style=color:hsl(350,100%,50%>i<a style=color:hsl(355,100%,50%>s<a style=color:hsl(360,100%,50%>. 

Ismael Miguel
sumber