머리말
이 물결이 사실일 줄은 몰랐어요 오후에 배불리 친구들과 자랑하고 chatgpt를 플레이한 다음 chatgpt가 이러한 효과를 얻을 수 있는 프로그램을 작성할 수 있는지 생각했습니다. 정렬 알고리즘을 보여줍니다. 입력 데이터를 사용자 지정하고 각 실행 결과를 표시합니다.
그런 다음 chatgpt가 생성하도록 한 다음, chatgpt와의 지속적인 디버깅 및 통신을 통해 마침내 보이는 돔을 얻습니다.
앞으로는 사용자가 이를 기반으로 코드를 입력하도록 지원할 것입니다. 이러한 효과를 얻으려면:
그러나 연고의 파리는 그것이 반환하는 코드에 항상 버그가 있고 레이아웃에 특정 문제가 있다는 것입니다.결국 코드는 디버깅을 위해 수동으로만 수정할 수 있습니다. 즉, 그는 코드의 90% 이상을 생성했고 나는 조립, 수정 및 디버깅만 담당했습니다. 특히 코드 생성기로는 불가능한 단순 로직의 구현 등 효율성은 확실히 향상되었지만 여전히 인간에 비해 상대적으로 번거로운 작업입니다.
데이터 프레임
다음으로 이 코드의 핵심 프로세스에 대해 간략하게 설명하겠습니다. 사실 이 코드는 매우 간단합니다.
new Vue({
el: '#app',
data: {
input: '5, 4, 3, 2, 1',
history: [],
currentFrame: -1,
maxFrame: -1,
intervalId: null,
},
methods: {
sort() {
this.history = [];
let list = this.input.split(',').map(Number);
let maxHeight = 10;
this.render(list.slice(), maxHeight);
for (let i = 0; i < list.length - 1; i++) {
for (let j = 0; j < list.length - i - 1; j++) {
if (list[j] > list[j + 1]) {
let temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
this.history.push(list.slice());
}
}
}
this.history.push(list.slice());
this.maxFrame = this.history.length - 1;
this.currentFrame = 0;
this.render(this.history[this.currentFrame], maxHeight);
this.updateLabel();
},
render(list, maxHeight) {
let outputDiv = document.getElementById('output');
outputDiv.innerHTML = '';
let scaleFactor = maxHeight / Math.max(...list);
for (let i = 0; i < list.length; i++) {
let bar = document.createElement('div');
bar.className = 'bar';
bar.style.height = `${
scaleFactor * 20 * list[i]}px`;
bar.innerText = list[i].toString();
outputDiv.appendChild(bar);
}
},
nextStep() {
if (this.currentFrame < this.maxFrame) {
this.currentFrame++;
this.render(this.history[this.currentFrame], 10);
this.updateLabel();
}
},
prevStep() {
if (this.currentFrame > 0) {
// 当前帧数大于0时才执行操作
this.currentFrame--;
this.render(this.history[this.currentFrame], 10);
this.updateLabel();
}
},
restart() {
this.currentFrame = -1;
this.sort();
},
updateLabel() {
let label = `Step ${
this.currentFrame + 1} of ${
this.maxFrame + 1}`;
document.getElementById('step-label').innerText = label;
},
play() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
} else {
this.intervalId = setInterval(() => {
if (this.currentFrame < this.maxFrame) {
this.nextStep();
} else {
clearInterval(this.intervalId);
this.intervalId = null;
}
}, 500);
}
},
},
mounted() {
this.sort();
},
});
여기에서 거품 정렬을 구현한 것을 볼 수 있습니다. 교환 또는 데이터 변경이 있을 때마다 현재 배열을 복사하여 기록 배열에 넣습니다. 그런 다음 When 호출에 표시됩니다. 원본 데이터를 가져온 다음 히스토그램을 만들어 데이터를 나타냅니다.
이것이 바로 이 코드입니다.
render(list, maxHeight) {
let outputDiv = document.getElementById('output');
outputDiv.innerHTML = '';
let scaleFactor = maxHeight / Math.max(...list);
for (let i = 0; i < list.length; i++) {
let bar = document.createElement('div');
bar.className = 'bar';
bar.style.height = `${
scaleFactor * 20 * list[i]}px`;
bar.innerText = list[i].toString();
outputDiv.appendChild(bar);
}
},
정렬 시각화
다음은 시각적 표시를 위한 전체 코드입니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Bubble Sort Visualization</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
.bar {
background-color: blue;
margin: 2px;
display: inline-block;
vertical-align: bottom;
width: 40px;
text-align: center;
color: white;
font-weight: bold;
}
#output {
margin-bottom: 20px;
}
#step-label {
font-size: 24px;
font-weight: bold;
margin-top: 10px;
width: 100%;
}
#app>form>.form-row {
display: flex;
align-items: center;
justify-content: space-between;
}
#app>form>.form-row>.col-sm-8 {
display: flex;
align-items: center;
padding-right: 5px;
}
#app>form>.form-row>.col-sm-4 {
display: flex;
align-items: center;
justify-content: flex-end;
flex-wrap: nowrap;
padding-left: 5px;
width: 180px;
}
#sort-button {
width: 70px !important;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-left: 5px;
}
#app>.row>.col-sm:not(:first-child) {
margin-top: 10px;
}
#play-button {
background-color: #007bff;
color: white;
border: none;
font-weight: bold;
width: 40px;
height: 40px;
border-radius: 50%;
position: relative;
transition: all .2s ease-in-out;
}
#play-button:hover {
opacity: 0.8;
}
#play-button:active:after {
content: "";
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 0;
height: 0;
border-style: solid;
border-width: 10px 0 10px 20px;
border-color: transparent transparent transparent #fff;
}
.btn-group>.btn {
margin-left: 5px;
margin-right: 5px;
}
</style>
</head>
<body>
<div id="app" class="container mt-5">
<h1 class="mb-5">Bubble Sort Visualization</h1>
<form>
<div class="form-row">
<div class="col-sm-8">
<label for="input" class="sr-only">Enter a list of numbers:</label>
<input type="text" class="form-control" id="input" v-model="input" placeholder="Enter a list of numbers">
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary btn-block" id="sort-button" @click="sort">Sort</button>
</div>
</div>
<br>
<div id="output"></div>
<div class="row">
<div class="col-sm-12 col-md">
<h3 class="text-center" id="step-label">Step 0 of 0</h3>
</div>
<div class="col-sm">
<div class="btn-group">
<button v-show="currentFrame >= 0" type="button" class="btn btn-secondary" @click="prevStep">Prev Step</button>
<button type="button" class="btn" id="play-button" @click="play">
<svg viewBox="0 0 100 100" width="50%">
<polygon points="0,0 0,100 100,50" fill="#fff"></polygon>
</svg>
</button>
<button v-show="currentFrame < maxFrame" type="button" class="btn btn-primary" @click="nextStep">Next Step</button>
<button v-show="currentFrame == maxFrame" type="button" class="btn btn-secondary" @click="restart">Restart</button>
</div>
</div>
</div>
</form>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
input: '5, 4, 3, 2, 1',
history: [],
currentFrame: -1,
maxFrame: -1,
intervalId: null,
},
methods: {
sort() {
this.history = [];
let list = this.input.split(',').map(Number);
let maxHeight = 10;
this.render(list.slice(), maxHeight);
for (let i = 0; i < list.length - 1; i++) {
for (let j = 0; j < list.length - i - 1; j++) {
if (list[j] > list[j + 1]) {
let temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
this.history.push(list.slice());
}
}
}
this.history.push(list.slice());
this.maxFrame = this.history.length - 1;
this.currentFrame = 0;
this.render(this.history[this.currentFrame], maxHeight);
this.updateLabel();
},
render(list, maxHeight) {
let outputDiv = document.getElementById('output');
outputDiv.innerHTML = '';
let scaleFactor = maxHeight / Math.max(...list);
for (let i = 0; i < list.length; i++) {
let bar = document.createElement('div');
bar.className = 'bar';
bar.style.height = `${
scaleFactor * 20 * list[i]}px`;
bar.innerText = list[i].toString();
outputDiv.appendChild(bar);
}
},
nextStep() {
if (this.currentFrame < this.maxFrame) {
this.currentFrame++;
this.render(this.history[this.currentFrame], 10);
this.updateLabel();
}
},
prevStep() {
if (this.currentFrame > 0) {
// 当前帧数大于0时才执行操作
this.currentFrame--;
this.render(this.history[this.currentFrame], 10);
this.updateLabel();
}
},
restart() {
this.currentFrame = -1;
this.sort();
},
updateLabel() {
let label = `Step ${
this.currentFrame + 1} of ${
this.maxFrame + 1}`;
document.getElementById('step-label').innerText = label;
},
play() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
} else {
this.intervalId = setInterval(() => {
if (this.currentFrame < this.maxFrame) {
this.nextStep();
} else {
clearInterval(this.intervalId);
this.intervalId = null;
}
}, 500);
}
},
},
mounted() {
this.sort();
},
});
</script>
</body>
</html>
언급할 가치가 없는 것은 이 결과는 chatgpt 통신을 여러 번 한 후에 얻은 결과이므로 천천히 안내해야 합니다.
지원 편집기
다음은 업그레이드를 해서 chatgpt를 에디터에 참여하게 했는데 이 부분은 성능이 좋지 않아서 그냥 선반만 올려놓고 주로 로직을 직접 구현해서 여기서는 수동으로 수정해서 몇 가지를 추가했습니다. 코드는 물론 많지 않고 추가 편집기 일 뿐이며 입력 코드를 읽는 부분을 추가하면 충분하지 않습니다.여기서는 보안 필터링없이 eval로만 구현되며 로컬에서 실행되며 자바스크립트만 지원합니다.
그러면 전체 코드는 다음과 같습니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>666算法可视化平台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.min.css">
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
.bar {
background-color: blue;
margin: 2px;
display: inline-block;
vertical-align: bottom;
width: 40px;
text-align: center;
color: white;
font-weight: bold;
}
#output {
margin-bottom: 20px;
}
#step-label {
font-size: 24px;
font-weight: bold;
margin-top: 10px;
width: 100%;
}
#app>form>.form-row {
display: flex;
align-items: center;
justify-content: space-between;
}
#app>form>.form-row>.col-sm-8 {
display: flex;
align-items: center;
padding-right: 5px;
}
#app>form>.form-row>.col-sm-4 {
display: flex;
align-items: center;
flex-wrap: nowrap;
padding-left: 5px;
width: 60px;
}
#sort-button {
width: 70px !important;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-left: 1px;
}
#app>.row>.col-sm:not(:first-child) {
margin-top: 10px;
}
#play-button {
background-color: #007bff;
color: white;
border: none;
font-weight: bold;
width: 40px;
height: 40px;
border-radius: 50%;
position: relative;
transition: all .2s ease-in-out;
}
#play-button:hover {
opacity: 0.8;
}
#play-button:active:after {
content: "";
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 0;
height: 0;
border-style: solid;
border-width: 10px 0 10px 20px;
border-color: transparent transparent transparent #fff;
}
.btn-group>.btn {
margin-left: 5px;
margin-right: 5px;
}
</style>
</head>
<body>
<div id="app" class="container mt-5">
<h1 class="mb-5">666算法可视化平台</h1>
<form>
<div class="form-row">
<div class="col-sm-8">
<label for="input" class="sr-only">Enter a list of numbers:</label>
<input type="text" class="form-control" id="input" v-model="input" placeholder="Enter a list of numbers">
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary btn-block" id="sort-button" @click="sort">Sort</button>
</div>
</div>
<br>
<div id="output"></div>
<div class="row">
<div class="col-sm-12 col-md">
<h3 class="text-center" id="step-label">Step 0 of 0</h3>
</div>
<div class="col-sm">
<div class="btn-group">
<button v-show="currentFrame >= 0" type="button" class="btn btn-secondary" @click="prevStep">Prev Step</button>
<button type="button" class="btn" id="play-button" @click="play">
<svg viewBox="0 0 100 100" width="50%">
<polygon points="0,0 0,100 100,50" fill="#fff"></polygon>
</svg>
</button>
<button v-show="currentFrame < maxFrame" type="button" class="btn btn-primary" @click="nextStep">Next Step</button>
<button v-show="currentFrame == maxFrame" type="button" class="btn btn-secondary" @click="restart">Restart</button>
</div>
</div>
</div>
<textarea id="code"></textarea>
</form>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/mode/javascript/javascript.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
input: '5, 4, 3, 2, 1',
history: [],
currentFrame: -1,
maxFrame: -1,
intervalId: null,
editor: null,
code: `//欢迎使用666可视化工具,目前只支持JS
function bubbleSort(arr,that) {
// arr是固定参数
let len = arr.length;
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
// 存储每一次交换的结果,固定格式
that.history.push(arr.slice());
}
}
}
}`
},
methods: {
sort() {
this.history = [];
let list = this.input.split(',').map(Number);
let maxHeight = 10;
this.render(list.slice(), maxHeight);
if (this.hasCode()) {
let coeds = this.getCode()
let fn = eval(`(${
coeds})`);
fn(list, this);
} else {
for (let i = 0; i < list.length - 1; i++) {
for (let j = 0; j < list.length - i - 1; j++) {
if (list[j] > list[j + 1]) {
let temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
this.history.push(list.slice());
}
}
}
}
this.history.push(list.slice());
this.maxFrame = this.history.length - 1;
this.currentFrame = 0;
this.render(this.history[this.currentFrame], maxHeight);
this.updateLabel();
},
render(list, maxHeight) {
let outputDiv = document.getElementById('output');
outputDiv.innerHTML = '';
let scaleFactor = maxHeight / Math.max(...list);
for (let i = 0; i < list.length; i++) {
let bar = document.createElement('div');
bar.className = 'bar';
bar.style.height = `${
scaleFactor * 20 * list[i]}px`;
bar.innerText = list[i].toString();
outputDiv.appendChild(bar);
}
},
nextStep() {
if (this.currentFrame < this.maxFrame) {
this.currentFrame++;
this.render(this.history[this.currentFrame], 10);
this.updateLabel();
}
},
prevStep() {
if (this.currentFrame > 0) {
// 当前帧数大于0时才执行操作
this.currentFrame--;
this.render(this.history[this.currentFrame], 10);
this.updateLabel();
}
},
restart() {
this.currentFrame = -1;
this.sort();
},
updateLabel() {
let label = `Step ${
this.currentFrame + 1} of ${
this.maxFrame + 1}`;
document.getElementById('step-label').innerText = label;
},
play() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
} else {
this.intervalId = setInterval(() => {
if (this.currentFrame < this.maxFrame) {
this.nextStep();
} else {
clearInterval(this.intervalId);
this.intervalId = null;
}
}, 500);
}
},
getCode() {
return this.editor.getValue();
},
hasCode() {
let code = this.getCode();
return code.trim().length > 0;
},
},
mounted() {
this.editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
mode: "text/javascript",
tabSize: 2,
theme: "default",
});
this.editor.setValue(this.code);
this.sort();
},
});
</script>
</body>
</html>
요약하다
한 사람이 한 팀이고, 앞으로는 더 이상 장난이 아닙니다. 앞으로는 사장님이 비용을 아끼기 위해 우리를 열어야 할까요, 아니면 수입을 늘리기 위해 사장님을 열어야 할까요?