CSS&JS/⚡Thinkers

[JS]무작위로 LOVE 나올 때 까지 문자열 출력

arancia_ 2024. 5. 20. 13:30

원본 작품 : https://x.com/ntv_rd/status/1792053852889612311

 

X의 日テレR&Dラボ님(@ntv_rd)

LOVEが現れるまでランダムに文字列を生成し続ける作品、エキソニモさんの『Find My LOVE』。37万文字描いてやっと出会えました。シンプルだけど奥深い。面白い。 アートキャンバスとしてのWeb

twitter.com

무작위로 A-Z까지 알파벳중 랜덤으로 출력하여 최종적으로 LOVE라는 글자가 출력될 때 까지 시간을 계산한다.
근데 이거 실제로 돌려보면 한평생 걸릴 가능성이 크기 때문에 다른 글자도 입력해서 테스트 할 수 있도록 해놓았다.

코드펜 데모

 

See the Pen RANDOM LOVE by Oh Ikmyeong (@dpffpself) on CodePen.

 

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>무작위 LOVE 나올때까지</title>
    <link rel="stylesheet" href="./style.css"/>
    <script src="./main.js" type="module"></script>
</head>
<body>
    <form id="frm">
        <input id="answer" type="text" value="LOVE" pattern="[A-Z]+"/>
        <button type="submit">CHANGE WORD</button>
    </form>
    <div id="result"></div>
    <div id="time">Searching...</div>
    <button id="btn">STOP</button>
</body>
</html>
cs

 

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@charset "utf-8";
@import url('https://fonts.googleapis.com/css2?family=Josefin+Slab:ital,wght@0,100..700;1,100..700&display=swap');
*{margin:0;padding:0;box-sizing:border-box;}
body{
    width:100%;min-height:100vh;
    background:#000;
    font-family: "Josefin Slab", serif;
    color:#fff;
}
 
#result,
#time{
    position:relative;
    width:100%;max-width:1200px;
    margin:0 auto;
}
 
#result{
    display:flex;flex-flow:row wrap;
    gap:15px 5px;
    position:relative; overflow:auto;
    max-height:70vh;
    padding:80px 20px 40px;
    text-align:center;
    text-transform:uppercase;
    font-size:24px; font-weight:600;
}
 
#result span{
    width:1.2em;
}
#result span.has{
    color:rgb(114, 223, 250);
}
#result span.red{
    background:rgba(255, 0, 0, 0.248);
    color:red;
}
 
#time{
    padding:0 20px;
    font-family:san-serif;
    font-size:14px;
}
 
button{
    display:block;
    min-width:120px;height:48px;
    padding:0 20px;
    background:transparent;
    border:1px solid white; border-radius:4px;
    color:white; font-size:12px;
}
#btn{
    margin:20px auto 40px;
}
 
#frm{
    display:flex;flex-flow:row wrap;
    justify-content:center; align-items:center;
    gap:10px;
    position:relative;
    padding:40px 20px 20px;
}
 
[type="text"]{
    height:48px; width:200px;
    padding:0 20px;
    background:rgba(255,255,255,.1);
    border:none; border-radius:4px;
    color:#fff;font-size:18px;text-align:center; font-weight:bold;
}
cs

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { SearchLove } from "./SearchLove.js";
 
const $result = document.getElementById("result");
const $time = document.getElementById("time");
const $btn = document.getElementById("btn");
const $form = document.getElementById("frm");
let startTime,endTime,executionTime;
let timer;
 
const SL = new SearchLove();
 
$btn.addEventListener("click",()=>{
    $btn.classList.toggle("off");
    if($btn.classList.contains("off")){
        stop();
        $btn.textContent = "START"
    }else{
        write_letter();
        $btn.textContent = "STOP"
    }
});
 
$form.addEventListener("submit",(e)=>{
    e.preventDefault();
    on_submit_form();
});
 
(function(){
    on_submit_form();
})();
 
function write_letter(){
    const str = SL.get_letter();
    const $str = document.createElement("SPAN");
    $str.textContent = str;
    if(SL.answer_includes(str)){$str.classList.add("has");}
    $result.appendChild($str);
    
    if(SL.compare_letter(str)){
        stop();
        display_execution_time();        
        display_red_letter();
        return;
    }
 
    timer = setTimeout(write_letter,50);
}//write_letter
 
function stop(){
    clearTimeout(timer);
    timer = null;
}//stop
 
function display_execution_time(){
    endTime = Date.now();
    executionTime = endTime - startTime;
    const hour = executionTime / (1000 * 60 * 60);
    const min = executionTime / (1000 * 60);
    const sec = executionTime % (1000 * 60 * 60);
    $time.textContent = `${parseInt(hour)}시 ${parseInt(min)}분 ${(sec / 1000).toFixed(1)}초가 걸렸습니다.`;
}//display_execution_time
 
function display_red_letter(){
    $result.classList.add("done");
    const $$span = $result.querySelectorAll(`SPAN:nth-last-child(${SL.get_answer_length() + 1}) ~ SPAN`);
    $$span.forEach($span=>$span.classList.add("red"));
}//display_red_letter
 
function on_submit_form(){
    stop();
    $result.innerHTML = "";
    $time.innerHTML = "Searching"
 
    /* time */
    startTime = Date.now();
 
    const answer= document.getElementById("answer").value;
    SL.set_answer(answer);
    SL.set_info();
    SL.reset_count();
    SL.reset_index();
 
    write_letter();
}//on_submit_form
cs

SearchLove.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
export class SearchLove{
    #ANSWER;
 
    constructor(){
        this.IDX = 0;
        this.info = null;
        this.LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        this.temp;
        this.COUNT = 0;
    }//constructor
 
    set_answer(ANSWER){
        this.#ANSWER = ANSWER;
        return this;
    }//set_answer
 
    get_answer_length(){return this.#ANSWER.length;}
 
    set_info(){
        this.info = new Map();
        this.#ANSWER.split("").forEach((str,idx)=>{
            this.info.set(idx,str);
        });
        console.log(this.info);
    }//set_info
 
    set_temp(){
        this.temp = this.LETTERS.split("");
    }//set_temp
 
    reset_count(){
        this.COUNT = 0;
    }//reset_count
    
    reset_index(){
        this.IDX = 0;
    }//reset_index
 
    get_letter(){
        if(!this.temp?.length || !this.temp){
            console.log(`${++this.COUNT}번째 알파벳 세트`);
            this.set_temp();
        }
        const idx = parseInt(Math.random() * this.temp.length);
        const char = this.temp.splice(idx,1)[0]; 
        return char;
        // return this.LETTERS.charAt(idx);
    }//get_letter
 
    compare_letter(str){
        const bool = str === this.info.get(this.IDX);
        if(bool){
            this.IDX++;
            console.log(this.IDX);
        }else{
            this.reset_index();
        }
 
        if(this.IDX >= this.#ANSWER.lengthreturn true;
        return false;
    }//compare_letter
 
    answer_includes(str){
        const bool = this.#ANSWER.includes(str); 
        return bool;
    }//answer_includes
}//class-SearchLove
cs