3 ポイント 投稿者 GN⁺ 2024-08-30 | 1件のコメント | WhatsAppで共有
  • インターネットを見て回っていると、興味深いASCIIアートのコンポーネントを見つけた。見た目は素晴らしかったが、実装方法を理解するのは難しかった
  • ソースコードを確認したが、コードは圧縮(Minified)されていた

圧縮されたコードの例

  • コードの一部は次のとおり:
    const { floor: ra, abs: KE, min: QE } = Math,  
      O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"],  
      G7 = Date.now() % 3 ? O5[1] : O5[0],  
      V5 = G7.length,  
      JE = { fps: 60 };  
    

ChatGPTにコードの説明を依頼

  • ChatGPTに「コードを説明してほしい」と依頼した
  • ChatGPTの回答:

    提供されたコードはかなり複雑ですが、各部分とその機能をわかりやすく説明します。

概要

  • JavaScriptを使って複数の関数とコンポーネントを定義している
  • Reactアプリケーションで動的なテキストコンテンツを生成している
  • ASCIIアート、または事前定義された文字セットを用いた視覚効果を生成している

主なコンポーネントと関数

  1. 文字セットの選択:
const { floor: ra, abs: KE, min: QE } = Math;  
const O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"];  
const G7 = Date.now() % 3 ? O5[1] : O5[0];  
const V5 = G7.length;  
  • Mathの関数を取り込み、2つの文字セットを定義している
  • 現在時刻に応じて文字セットを選択している
  • 選択した文字セットの長さを保存している
  1. 動的文字選択関数:
function eT(e, t, n, r) {  
  const i = t.time * 8e-5;  
  const s = QE(t.cols, t.rows);  
  const o = t.metrics.aspect * 0.2;  
  const l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s };  
  const u = ra(KE(YE(l) - i) * V5 + (ra(e.x / 1) % 2) * 2) % V5;  
  return G7[u];  
}  
  • eT関数は入力位置と現在時刻に応じて文字を生成する
  • 位置を調整し、文字セットから文字を選択する
  1. 動的コンテンツを表示するReactコンポーネント (tT):
const tT = () => {  
  const e = j.useRef(null);  
  const [t, n] = j.useState({ height: null, width: null });  
  j.useEffect(() => {  
    function r() {  
      n({ height: window.innerHeight, width: window.innerWidth });  
    }  
    if (typeof window < "u") {  
      n({ height: window.innerHeight, width: window.innerWidth });  
      window.addEventListener("resize", r);  
      return () => window.removeEventListener("resize", r);  
    }  
  }, []);  
  j.useEffect(() => {  
    const r = e.current;  
    if (!r) return;  
    const i = 12;  
    const s = ra(t.width / i) * 1.6;  
    const o = ra(t.height / i);  
    const l = { aspect: s / o };  
    const u = setInterval(() => {  
      let c = "";  
      for (let d = 0; d < o; d++) {  
        for (let f = 0; f < s; f++) c += eT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() });  
        c += `  `;  
      }  
      r.textContent = c;  
    }, 1e3 / JE.fps);  
    return () => clearInterval(u);  
  }, [t]);  
  return a.jsx("div", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("div", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) });  
};  
  • このReactコンポーネントは、定期的に div 要素の内容を動的に生成された文字で更新する
  • ウィンドウサイズに応じて列数と行数を計算し、div を文字で埋める

TypeScriptに変換されたコード

  • ChatGPTにTypeScriptへ変換したコードを依頼した
  • ChatGPTの回答:
    import React, { useEffect, useRef, useState } from 'react';  
    const selectedCharacterSet = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ";  
    const characterSetLength = selectedCharacterSet.length;  
    
    const calculateCharacter = (  
      x: number,  
      y: number,  
      cols: number,  
      rows: number,  
      aspect: number,  
      time: number,  
    ): string => {  
      const timeFactor = time * 0.000_08;  
      const size = Math.min(cols, rows);  
      const aspectRatio = aspect * 0.2;  
      const position = {  
        x: ((4 * (x - cols / 6.25)) / size) * aspectRatio,  
        y: (5 * (y - rows / 4)) / size,  
      };  
      const index = Math.floor(  
        Math.abs(  
          Math.cos(position.x * position.x - position.y * position.y) - timeFactor,  
        ) * characterSetLength + (Math.floor(x) % 2) * 2,  
      ) % characterSetLength;  
      return selectedCharacterSet[index];  
    };  
    
    type Size = {  
      height: null | number;  
      width: null | number;  
    };  
    
    const AsciiArtGenerator: React.FC = () => {  
      const textRef = useRef(null);  
      const [size, setSize] = useState({ height: null, width: null });  
    
      useEffect(() => {  
        const handleResize = () => {  
          setSize({ height: window.innerHeight, width: window.innerWidth });  
        };  
        handleResize();  
        window.addEventListener('resize', handleResize);  
        return () => {  
          window.removeEventListener('resize', handleResize);  
        };  
      }, []);  
    
      useEffect(() => {  
        const element = textRef.current;  
        if (!element || !size.width || !size.height) return undefined;  
    
        const cols = Math.floor(size.width / 12) * 1.6;  
        const rows = Math.floor(size.height / 12);  
        const aspectRatio = cols / rows;  
    
        const intervalId = setInterval(() => {  
          let content = '';  
          for (let y = 0; y < rows; y++) {  
            for (let x = 0; x < cols; x++) {  
              content += calculateCharacter(x, y, cols, rows, aspectRatio, Date.now());  
            }  
            content += '\n';  
          }  
          element.textContent = content;  
        }, 1_000 / 60);  
    
        return () => {  
          clearInterval(intervalId);  
        };  
      }, [size]);  
    
      return (  
    
      );  
    };  
    
    export default () => {  
      return ;  
    };  
    

GN⁺のまとめ

  • この記事は、圧縮されたコードを理解し復元する方法を説明している
  • ChatGPTを使って複雑なコードを説明し、TypeScriptへ変換する過程を示している
  • コードの復元と理解を助けるためにAIツールを活用する方法を提示している
  • 類似機能を持つプロジェクトとして PrettierUglifyJS がある

1件のコメント

 
GN⁺ 2024-08-30
Hacker Newsの意見
  • HumanifyJSの作者がLLMベースのツールを開発した。このツールはASTレベルでLLMを使い、unminification後もコードが動作することを保証する

  • JSのminificationは機械的で比較的単純だ。手作業で行うには面倒だが、変換自体は限定的なので、多少メモを取りながら識別子を追えば読むことはできる

  • 一般的なunminificationやobfuscation解除は、依然として未解決の問題だ。過去に意図的に難読化したプログラムを書いたことがあるが、ChatGPTは表面的なレベルですら理解できなかった

    • 例: 160バイト長のBrainfuckインタプリタをGPT-4が説明しようとしたが、元のコードとはまったく似ていなかった
    • サンプルコードリンク
  • 一部の開発者は難読化のためにminificationを使うので、不満を持つかもしれない。ColdFusionの以前のバージョンで提供されていたコード"暗号化"ツールは弱いアルゴリズムだったにもかかわらず、安全だと思って使っていた人たちがいた

  • タイトルではOpenAIよりもChatGPTやgpt-4を使うほうが適切かもしれない

  • これは人間を上回る知的性能の一例だ。LLMはunminificationを理解しており、この特定のテーマでは人間より優れている

  • LLMはテキスト変換に優れている。これが彼らの中核的な強みだ

  • 約1年前、GPTを使ってマルウェアの難読化解除を試みたが、自分でコードを分析するほうがよかった。最近もう一度試したところ、ある程度は理解できていた

    • 例: ページロードを検知し、計算を行い、悪意のあるサイトへリダイレクトするロジックを把握した
    • レポートリンク
  • LLMを使って複雑なコードをより読みやすくするのは非常に解放感がある。ときどき詳細を見落とすことはあるが、それは自分で確認できる

    • コードの目的は理解していても、なぜ特定の方法で書かれているのか分からないとき、LLMに質問して新しい洞察を得ることができる
    • 使用例リンク
  • unminifiedコードがminifiedコードと一致しなければ、有用性は大きく低下する。多くの場合、コードを実行した後では差分を確認できない

  • Webサイトの計算アルゴリズムを知りたいとき、minifiedされたJSをChatGPTに入力すれば簡単に把握できた。LLMが完全なSaaSアプリをクローンできる未来も想像できる

    • 例: HubSpotクローンを作るために、LLMがブラウザと対話し、UIを分析し、バックエンドアーキテクチャを提案できるかもしれない
    • AIは将来的に強力なデフレ要因になるだろう