24691116의 등록된 링크

 24691116로 등록된 네이버 블로그 포스트 수는 393건입니다.

다항식 더하기 - 프로그래머스 [내부링크]

// 덧셈으로 이루어진 다항식이 매개변수 // 동류항끼리 더한 값을 문자열로 return // 정수, x, + 기호로만 이루어져있다. function solution(polynomial) { let xNum = 0; // x항의 상수 let num = 0; // 상수항 // x가 포함되는지 확인하는 함수 const isX = (a) => { const regExp = /x/; return regExp.test(a) ? true : false; }; // 문자열을 배열로 변경 const arr = polynomial.split(" "); for (const a of arr) { // x가 포함되어 있다면 if (isX(a)) { // 만약 계수가 1이라면 if (a[0] === "x") { xNum += 1; } else { // 계수가 1이 아니라면 xNum += +a.split("x")[0]; } // 숫자라면 } else { if (a !== "+") { num += +a; }

JavaScript 함수형 프로그래밍 - 합성 관점에서의 Promise와 모나드 [내부링크]

함수 합성 어떤 함수 g에 전달한 매개변수를 통한 결과값이 함수 f에 전달되는 것 - f(g(x)) 모나드 상황에 따라 안전하게 함수를 합성할 수 있게 하기 위한 도구 const g = a => a + 1; const f = a => a * a; // 정상적인 값을 할당할 때는 잘 동작한다. console.log(f(g(1))); // 4 // 하지만 빈 값이나 비정상적인 값을 전달하면 에러가 나거나 // 비정상적인 값이 만들어진다. // 즉, 안전하게 합성이 되었다고 할 수 없다. console.log(f(g())); // NaN // 모나드가 적용된 안전한 함수 합성 [1].map(g).map(f).forEach(r => console.log(r)) // 1 // 만약 빈 값이 들어오면 아무것도 출력하지 않는다. [].map(g).map(f).forEach(r => console.log(r, 10)) // Promise의 함수 합성 과정 Promise는 비동기적인 과정을 안전하게

JavaScript 함수형 프로그래밍 - Kleisli Composition 관점에서의 Promise [내부링크]

Kleisli Composition 관점에서의 Promise Promise는 Kleisli Composition을 지원하는 도구이다. Kleisli Composition Kleisli Arrow라고 불리기도 하는 함수 합성 방법이다. 오류가 있을 수 있는 상황에서의 함수 합성을 안전하게 하는 하나의 규칙이다. // Kleisli Composition 적용 전 const users = [ { id: 1, name: 'aa' }, { id: 2, name: 'bb' }, { id: 3, name: 'cc' }, ]; const getUserById = id => find(u => u.id === id, users); const f = ({name}) => name; const g = getUserById; const fg = id => f(g(id)); console.log(fg(2)); // bb users.pop(); users.pop(); console.log(fg(2)) // E

JavaScript 함수형 프로그래밍 - go, pipe, reduce에서 비동기 제어 [내부링크]

go 함수는 reduce를 사용하는 함수이고 pipe 함수는 go 함수를 사용하는 함수이다. 따라서 reduce 함수를 수정하면 go, pipe 함수도 비동기적인 코드를 제어할 수 있다. go(1, a => a + 10, a => Promise.resolve(a+100), a => a + 100, a => a + 1000, console,log); // 방법 1 // 중간에 Promise를 만나게 되면 연속적으로 비동기처리가 일어난다. // 즉, 불필요한 load 혹은 성능 저하가 발생할 수 있다. const reduce = (f, acc=0, iter) => { if (!iter) { iter = acc[Symbol.iterator](); acc = iter.next().value; } else { iter = iter[Symbol.iterator](); } let cur; while(!(cur=iter.next()).done) { const a = cur.value; acc =

JavaScript 함수형 프로그래밍 - Promise, then의 중요한 규칙 [내부링크]

Promise, then의 중요한 규칙 then 메소드를 통해서 결과를 꺼냈을 때의 값이 반드시 Promise가 아니다. Promise chain이 연속적으로 대기가 걸려 있어도 내가 원하는 곳에서 한번의 then으로 해당하는 결과를 받을 수 있다. // 예시 1 Promise.resolve(Promise.resolve(Promise.resolve(1))).then(console.log); // 1 // 예시 2 new Promise(resolve => resolve(new Promise(resolve => resolve(1)))).then(console.log);// 1 참고 함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의 ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍, map/filter/reduce, 파이프라인, 제너

JavaScript 함수형 프로그래밍 - 지연평가 + Promise [내부링크]

지연평가 + Promise 비동기 상황을 제어할 수 있게 코드를 변경 // 현재 코드에서는 Promise를 처리하지 못한다. go([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)], L.map(a => a + 10), take(2), console.log ) // 수정 코드 const go1 = (a, f) => a instanceof Promise ? a.then(f) : f(a); L.map = curry(function *(f, iter) { for (const a of iter) yield go1(a,f); }); take const take = curry((limit, iter) => { let res = []; iter = iter[Symbol.iterator](); return function recur() { let cur; while(!(cur=iter.next()).done) { const a = cur.v

JavaScript 함수형 프로그래밍 - Kleisli Composition : L.filter, nop, take + Promise [내부링크]

L.filter nop : Promise.reject을 했을 시 에러가 아닌 값을 전달하지 않겠다는 구분자 역할 Promise.reject가 존재하면 then이 몇 개 존재하든 바로 catch 부분의 코드가 실행되게 된다. // 현재는 Promise를 filter하지 못한다. go([1,2,3,4,5,6], L.map(a => Promise.resolve(a * a)), L.filter(a => a % 2), take(2), console.log ) // 수정 코드 const nop = Symbol('nop'); const go1 = (a, f) => a instanceof Promise ? a.then(f) : f(a); L.filter = curry(function *(f, iter) { for (const a of iter) { const b = go1(a, f); if (b instanceof Promise) yield b.then(b => b ? a : Promise.rej

JavaScript 함수형 프로그래밍 - reduce에서 nop 지원 [내부링크]

현재 코드는 에러가 발생한다. go([1,2,3,4], L.map(a => Promise.resolve(a * a)), L.filter(a => Promise.resolve(a % 2)), reduce((a,b) => a + b), console.log ); 변경 전 코드 const go1 = (a, f) => a instanceof Promise ? a.then(f) : f(a); const reduce = (f, acc=0, iter) { if (!iter) { iter = acc[Symbol.iterator](); acc = iter.next().value; } else { iter = iter[Symbol.iterator](); } return go1(acc ,function recur(acc) { let cur; while(!(cur=iter.next()).done) { const a = cur.value; acc = f(acc, a); if (acc instanceof P

JavaScript 함수형 프로그래밍 - 지연된 함수열을 병렬적으로 평가하기 [내부링크]

자바스크립트가 동작하는 환경(브라우저, node.js)에서는 비동기 IO로 동작한다. 비동기 IO는 Single Thread를 기반으로 해서 IO들을 동기적으로 처리하기 보다는 비동기적으로 처리를 해서 하나의 Thead에서도 CPU의 점유를 효율적으로 해서 IO 작업들을 조금 더 효율적으로 하는 트렌드이다. C.reduce 모두 동시에 출발시킨 값을 return 시키는 reduce 동기적으로 실행하는 reduce보다 시간이 훨씬 단축된다. const delay500 => a => new Promise(resolve => { console.log('hi~'); setTimeout(() => resolve(a),500); }); const add = (a, b) => a + b; // reduce를 사용한 예시 go([1,2,3,4,5], L.map(a => delay500(a * a)), L.filter(a => a % 2), reduce(add), console.log ) // hi

JavaScript 함수형 프로그래밍 - async / await [내부링크]

async / await 자바스크립트에서 비동기적으로 일어나는 상황을 동기적인 문장으로 다룰 수 있게 해주는 키워드 function delay(a) { return new Promise(resolve => setTimeout(() => resolve(a), 500)); } async function f1() { // Promise가 풀어질 때까지 기다렸다가 값이 할당된다. const a = await delay(10); console.log(a); // 10 } 해당하는 함수가 await를 하기 위해서는 반드시 Promise를 return하는 함수여야 한다. await는 Promise를 평가해준다. function delay(a) { return new Promise(resolve => setTimeout(() => resolve(a), 500)); } async function f1() { const a = await delay(10); console.log(a); //10 ret

숨어있는 숫자의 덧셈 - 프로그래머스 [내부링크]

// 문자열이 매개변수로 주어진다. // 문자열은 소문자, 대문자, 자연수로만 구성 // 문자열 안의 자연수들의 합을 return function solution(myString) { // 문자열을 순회하며 숫자를 찾는다. let res = 0; let num = ""; const regExp = /[0-9]/; for (const a of myString) { if (regExp.test(a)) { num += a; } else { res += +num; num = ""; } } // 이 부분은 마지막 반복문이 끝났을 경우 숫자의 덧셈이 덜 된 경우 추가적인 계산을 해준다. if (num !== "") { res += +num; } return res; } solution("aAb1B2cC34oOp"); 이 문제는 반복문과 정규 표현식을 활용하여 해결하였습니다. 반복문을 순회하면서 숫자가 존재하면 num이라는 변수에 문자열 덧셈을 이용해 수를 받은 뒤 문자가 나오면 결과값에 더하는

JavaScript 함수형 프로그래밍 - 함수 중첩 사용 및 비교 [내부링크]

함수 중첩 사용 for...of 구현 // 변경 전 const map = curry((f, iter) => { let reg = []; for (const a of iter) reg.push(f(a)); return reg; }); // 변경 후 const map = curry((f, iter) => { let reg = []; iter = iter[Symbol.iterator](); let cur; while(!(cur = iter.next()).done) { const a = cur.value; reg.push(f(a)); } return reg; }); range, map, filter, take, reduce 중첩 사용 const range = (length) => { let i = -1; let reg = []; while (++i < length) reg.push(i); return reg; } const map = curry((f, iter) => { let reg =

React - outlet을 활용한 navigation bar 구현하기 [내부링크]

React 프로젝트를 개발할 때 Navigation Bar를 구현하는 것은 흔한 일입니다. 사실 대부분의 웹 페이지에서는 Navigation Bar가 필수적인 요소로 사용됩니다. 현재 진행중인 프로젝트에서도 Navigation Bar를 사용해야 하는데 모든 컴포넌트에 Nav Bar를 적용시키면 번거로운 작업이기 때문에 App.tsx에 적용시켜 전역으로 사용하도록 했습니다. function App() { return ( <> <NavBar /> <Router> <Routes> <Route path="/" element={<UserWelcome />} /> </Routes> </Router> </> ); } 하지만 문제가 있었습니다. Nav Bar가 없는 컴포넌트도 존재하고 또 다른 형태의 Nav Bar를 가진 컴포넌트도 존재했습니다. 그래서 컴포넌트의 pathName을 기준으로 조건부로 Nav Bar를 보여주도록 만들었습니다. export default function NavBar()

JavaScript 함수형 프로그래밍 - 결과를 만드는 함수 reduce, take [내부링크]

map, filter는 지연성을 가질 수 있지만 reduce, take 함수는 연산을 시작하는 시작점을 알리는 함수라 볼 수 있다. reduce 활용 예제 queryStr 함수 만들기 객체로부터 URL의 queryStr 부분을 얻어내는 함수 const queryStr = obj => go( obj, Object.entries, map(([k, v]) => `${k}=${v}`), reduce((a, b) => `${a}&${b}`) ) // 간략화 const queryStr = pipe( Object.entries, map(([k, v]) => `${k}=${v}`), reduce((a, b) => `${a}&${b}`) ) console.log(queryStr({ limit: 10, offset: 10, type: 'notice'})); reduce 활용 예제 2 Array.prototype.join 보다 다형성이 높은 join 함수 배열이 아닌 이터레이터도 사용할 수 있는 함수

JavaScript 함수형 프로그래밍 - L.map, L.filter로 map과 filter 만들기 [내부링크]

L.map으로 map 만들기 L.map = curry(function *(f,iter) { iter = iter[Symbol.iterator](); let cur; while(!(cur=iter.next()).done) { const a = cur.value; yield f(a); } }) // 바꾼 map const map = curry((f, iter) => go( iter, L.map(f), // Infinity로 설정하면 앞의 L.map의 길이가 // 얼마든지 모두 가져와서 결과를 만들 수 있다. take(Infinity) )) // 축약 const map = curry(pipe( L.map, // Infinity로 설정하면 앞의 L.map의 길이가 // 얼마든지 모두 가져와서 결과를 만들 수 있다. take(Infinity) )) L.filter로 filter 만들기 L.filter = curry(function *(f, iter) { iter = iter[Symbol.it

JavaScript 함수형 프로그래밍 - L.flatten과 flatten [내부링크]

flatten 배열 내부의 배열을 전부 평탄화해서 1차원 배열로 만드는 역할 L.flatten 지연적으로 동작 const isIterable = a => a && a[Symbol.iterator]; L.flatten = function *(iter) { for (const a of iter) { if (isIterable(a)) { for (const b of a) yield b; } else yield a; } }; const it = L.flatten([[1,2],3,4,[5,6],[7,8,9]]); console.log(it.next()); //{value: 1, done: false} console.log(it.next()); //{value: 2, done: false} console.log(it.next()); //{value: 3, done: false} console.log([...it]) // [1,2,3,4,5,6,7,8,9] flatten 실행 즉시 배열을 생성

JavaScript 함수형 프로그래밍 - L.flatMap, flatMap [내부링크]

flatMap map과 flatten을 동시에 진행하는 함수 flatMap이 있는 이유는 JavaScript가 기본적으로 지연적으로 동작하지 않기 때문이다. 내장 flatMap과 flatten + map의 시간 복잡도는 같다. 내장 flatMap const arr = [[1,2],[3,4],[5,6,7]]; console.log(arr.flatMap(a => a)); // [1,2,3,4,5,6,7] console.log(arr.flatMap(a => a.map(a => a * a))) // [1,4,9,16,25,36,49] flatten + map const arr = [[1,2],[3,4],[5,6,7]]; console.log(flatten(arr.map(a => a.map(a => a*a)))); 지연적으로 동작하는 L.flatMap 다형성이 높은 이터러블을 활용한 flatMap L.flatMap = curry(pipe(L.map, L.flatten)); const flat

JavaScript 함수형 프로그래밍 - 이터러블 중심 프로그래밍 실무적인 코드 [내부링크]

함수형 프로그래밍은 데이터를 어떻게 구성할지 먼저 만들어내고 프로그래밍하는 것이 아니라 조합되어 있는 함수에 맞는 데이터를 구성하는 식으로 작성하는 것이다. 객체지향 프로그래밍은 데이터를 먼저 정리를 한 뒤 프로그래밍을 하는 것이지만 함수형 프로그래밍은 이미 만들어놓은 함수 조합을 바탕으로 데이터를 구성하는 것이다. 사용 예시 const users = [ { name: 'a', age: 21, family: [ { name: 'a1', age: 53 }, { name: 'a2', age: 47 }, { name: 'a3', age: 16 }, { name: 'a4', age: 15 } ]}, { name: 'b', age: 24, family: [ { name: 'b1', age: 58 }, { name: 'b2', age: 51 }, { name: 'b3', age: 19 }, { name: 'b4', age: 22 } ]}, { name: 'c', age: 31, family:

JavaScript 함수형 프로그래밍 - callback과 Promise [내부링크]

callback과 Promise callback과 Promise의 큰 차이점은 then을 통해 결과를 꺼내는 것이 아닌 비동기 상황을 일급 값으로 다룬다는 점이다. 즉, callback 함수는 비동기적인 상황을 다루는 것이 코드로만 표현이 되어있지만 Promise는 비동기 상황에 대한 값을 만들어 return한다. Promise는 Promise 클래스로 만들어진 instance를 반환한다. 그 값은 대기, 성공, 실패를 다루는 일급 값이다. Promise는 값으로 다루어지기 때문에 일급이고 변수에 할당되거나 함수에 할당될 수 있다. // callback function add10(a, callback) { setTimeout(() => callback(a + 10), 100); } const a = add10(5, (res) => { console.log(res); }); console.log(a) // undefined // promise function add20(a) { ret

JavaScript 함수형 프로그래밍 - filter [내부링크]

filter 이터러블의 각 요소들에게 조건을 적용하여 조건이 true인 요소들만 뽑아 새로운 배열을 만드는 함수 const products = [ { name: '반팔티', price: 15000 }, { name: '긴팔티', price: 20000 }, { name: '핸드폰케이스', price: 15000 }, { name: '후드티', price: 30000 }, { name: '바지', price: 25000 }, ] const filter = (f, iter) => { const res = []; for (const a of iter) { if (f(a)) res.push(a); } return res; } filter(p => p.price < 20000, products); filter(n => n % 2, function *() { yield 1; yield 2; yield 3; yield 4; yield 5; }()); // [1, 3, 5] 참고 함수형 프로그래밍

JavaScript 함수형 프로그래밍 - reduce [내부링크]

reduce 이터러블의 각 요소들 축약해 하나의 값으로 만드는 함수 const nums = [1, 2, 3, 4, 5]; const reduce = (f, acc = 0, iter) => { // 초기값을 선택적으로 받는 조건문 if (!iter) { iter = acc[Symbol.iterator](); acc = iter.next().value; } for (const a of iter) { acc = f(acc, a) } return acc; } const add = (a, b) => a + b reduce(add, 0, nums); reduce 활용 const products = [ { name: '반팔티', price: 15000 }, { name: '긴팔티', price: 20000 }, { name: '핸드폰케이스', price: 15000 }, { name: '후드티', price: 30000 }, { name: '바지', price: 25000 }, ] console

JavaScript 함수형 프로그래밍 - go [내부링크]

go go함수는 함수들과 인자를 전달해 값을 평가하는데 사용 연속적으로 하나의 일을 하는 함수 ⇒ reduce를 활용 const go = (...args) => reduce((a, f) => f(a) ,args) go( 0, a => a + 1, a => a + 10, a => a + 100, console.log ) // 111 go를 사용하여 읽기 좋은 코드로 만들기 const products = [ { name: '반팔티', price: 15000 }, { name: '긴팔티', price: 20000 }, { name: '핸드폰케이스', price: 15000 }, { name: '후드티', price: 30000 }, { name: '바지', price: 25000 }, ]; go( products, products => filter(p => p.price < 20000, products), products => map(p => p.price, products), price

JavaScript 함수형 프로그래밍 - pipe [내부링크]

pipe 함수를 return하는 함수 함수들이 나열되어 있는 합성된 함수를 만드는데 사용 내부에서 go함수를 사용하는 함수 const pipe = (...fs) => (a) => go(a, ...fs) const f = pipe( a => a + 1, a => a + 10, a => a + 100 ) f(0); // 여러개의 값을 받는 pipe 함수 const pipe = (f,...fs) => (...as) => go(f(...as), ...fs) go( add(0,1), a => a + 10, a => a + 100, console.log ) const f = pipe( (a,b) => a + b, a => a + 10, a => a + 100 ); console.log(f(0,1)); 참고 함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의 ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을

JavaScript 함수형 프로그래밍 - curry [내부링크]

curry curry함수는 함수를 받아서 함수를 return하고 인자를 받아서 원하는 갯수 만큼의 인자가 들어왔을 때 받아둔 함수를 나중에 평가시키는 함수 const curry = f => (a, ..._) => _.length ? f(a, ..._) : (..._) => f(a, ..._); const mult = curry((a, b) => a * b); console.log(mult(1)); // (..._) => f(a, ..._) console.log(mult(1)(2)); // 2 const mult3 = mult(3); console.log(mult3(10)); // 30 console.log(mult3(5)); // 15 console.log(mult3(3)); // 9 curry를 활용해 go를 더 읽기 좋은 코드로 만들기 // map const map = curry((f, iter) => { let res = []; for (const a of iter) { res

JavaScript 함수형 프로그래밍 - 활용 [내부링크]

총 수량, 총 가격 const products = [ { name: '반팔티', price: 15000, quantity: 1 }, { name: '긴팔티', price: 20000, quantity: 2 }, { name: '핸드폰케이스', price: 15000, quantity: 3 }, { name: '후드티', price: 30000, quantity: 4 }, { name: '바지', price: 25000, quantity: 5 }, ]; // map const map = curry((f, iter) => { let res = []; for (const a of iter) { res.push(f(a)); } return res; }); // filter const filter = curry((f, iter) => { const res = []; for (const a of iter) { if (f(a)) res.push(a); } return res; }); // red

JavaScript 함수형 프로그래밍 - Range와 느긋한 L.range [내부링크]

Range 숫자 하나를 받고 숫자 크기만한 배열을 return하는 함수를 구현 const range = (length) => { let i = -1; let res = []; while (++i < length) { res.push(i); } return res; }; const list = range(5); console.log(range(5)); // [0,1,2,3,4] console.log(reduce((a, b) => a + b, list)); // 10 느긋한 Range Range와 동작은 같지만 generator를 활용한 range이다. 실제 console.log를 해보면 iterator가 반환되는 것을 알 수 있다. const L = {}; L.range = function *(length) { let i = -1; while (++i < length) { yield i; } }; const list = L.range(5); console.log(L.range(5));

JavaScript 함수형 프로그래밍 - take [내부링크]

take 많은 값을 받아서 잘라주는 함수 Range를 사용하면 해당 길이만큼 배열을 만든 뒤 자르는 과정이 실행돼서 비효율적이지만 L.range를 사용하면 최대 배열만 정의된 뒤 이터레이터를 순회할 때 생성하기 때문에 조금 더 효율적인다. const take = (limit, iter) => { let res = []; for (const a of iter) { res.push(a); if (res.length === limit) return res; } return res; }; console.log(take(5, range(100000)); //[0, 1, 2, 3, 4] console.log(take(5, L.range(100000)); //[0, 1, 2, 3, 4] // curry 적용 const take = curry((limit, iter) => { let res = []; for (const a of iter) { res.push(a); if (res.length ==

JavaScript 함수형 프로그래밍 - 지연 평가(Lazy Evaluation) [내부링크]

지연평가 필요할 때까지 평가를 미루다가 필요한 순간에 해당하는 코드를 평가해 값을 만드는 기법 이터러블 중심 프로그래밍에서의 지연 평가 제때 계산법 느긋한 계산법 제너레이터/이터레이터 프로토콜을 기반으로 구현 L.map 지연성을 가진 map 함수 제너레이터/이터레이터 프로토콜을 이용하여 생성 L.map = function *(f, iter) { for (const a of iter) yield f(a); } const it = L.map(a => a + 10, [1,2,3]); console.log(it.next()); //{value: 11, done: false} console.log(it.next()); //{value: 12, done: false} console.log(it.next()); //{value: 13, done: false} console.log([...it]) // [11, 12, 13] L.filter 지연성을 가진 filter 함수 L.filter = fu

React - Select 태그 Error [내부링크]

프로젝에서 Select 태그를 사용하다보면 이런 경고 문구가 발생하는 경우가 있다. use the defaultValue or value props on <select> instead of setting selected on <option> <select> <option value="" disabled selected hidden> 지역을 선택해주세요 </option> <option value="1">1</option> <option value="1">2</option> <option value="1">3</option> <option value="1">4</option> </select> 위의 코드를 사용하면 볼 수 있는 에러인데 React에서는 selected를 사용하면 발생하는 경고문인 것 같았다. 화면은 잘 나오지만 콘솔을 확인해보면 빨간줄 글이 생겨서 불편하다. 이것을 다른 방식으로 표현하면 해결할 수 있다. const options = [ { value: "", text:

D3 - 네트워크 데이터 시각화 [내부링크]

1. 시각화 예제 D3 공식 홈페이지 예제로는 아래 링크를 제공하고 있습니다. Networks 챕터에 Force-Directed(힘-방향) 그래프입니다. Force-Directed Graph / D3 | Observable // Copyright 2021 Observable, Inc. // Released under the ISC license. // https://observablehq.com/@d3/force-directed-graph function ForceGraph ( { nodes , // an iterable of node objects (typically [{id}, …]) links // an iterable of link objects (typically [{source, target}, …]) } , { nodeId = d => d... observablehq.com 2. 기반되는 메서드 인력과 척력 : 노드가 서로를 당기거나 밀어내는 힘입니다. 주로 .force

React - github에 배포하기 [내부링크]

수동 업로드 github repository를 생성한다. settings -> pages -> Source가 none인 부분을 main으로 변경 뒤 저장한다. 생성된 url이 배포시 사용할 주소이다. 아래 코드를 package.json에 추가한다. 생성된 url을 package.json에 붙여넣는다. { "homepage":"github page url", ... } npm run build를 하여 프로젝트를 build한다. build 안에 있는 파일을 그대로 github pages에 업로드하면 된다. 2. 자동 업로드 npm run build하면 build 폴더로 resource 파일들이 올라옵니다. npm install gh-pages 한 다음에 아래 코드를 package.json에 추가하고 { "homepage":"github 배포 url", ... "scripts" : { ... "deploy" : "gh-pages -d build" } } npm run deploy - ad

JavaScript 함수형 프로그래밍 - 평가와 일급 [내부링크]

평가와 일급 평가 코드가 계산(Evaluation) 되어 값을 만드는 것 일급 값으로 다룰 수 있다. 변수에 담을 수 있다. 함수의 인자로 사용될 수 있다. 함수의 결과로 사용될 수 있다. 일급 함수 함수를 값으로 다룰 수 있다. 조합성과 추상화의 도구 예제 const add5 = a => a + 5; console.log(add5); // a + 5 console.log(add5(5)); // 10 const f1 = () => () => 1; console.log(f1()); // () => 1 참고 함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의 ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍, map/filter/reduce, 파이프라인, 제너레이터를 통한 지연 평가, Pr... www.inflearn.com

JavaScript 함수형 프로그래밍 - 고차함수 [내부링크]

정의 함수를 값으로 다루는 함수 종류 함수를 인자로 받아서 실행하는 함수(applicative 프로그래밍) 예제1 const apply1 = f => f(1); const add2 = a => a + 2; console.log(apply1(add2)) // 3 console.log(apply1(a => a - 1)) // 0 예제2 const times = (f, n) => { let i = -1; while(++i < n) f(i); } times(console.log,3) // 0 1 2 times(a => console.log(a + 10), 3); // 10 11 12 함수를 만들어 리턴하는 함수 (클로저를 만들어 리턴하는 함수) 예제 const addMaker = a => b => a + b const add10 = addMaker(10); // b => 10 + b console.log(add10(5)); // 15 console.log(add10(10)); // 20 참

JavaScript 함수형 프로그래밍 - 이터러블/이터레이터 [내부링크]

ES5와 ES6의 리스트 순회 차이 for...of를 통해 이터러블을 순회할 수 있다. // ES5 const list = [1,2,3]; for(let i = 0; i < list.lenght; i++) { console.log(list[i]); // 1 2 3 }; const str = 'abc'; for(let i = 0; i < list.lenght; i++) { console.log(str[i]); // 1 2 3 }; // ES6 for (const a of list) { console.log(a); } for (const a of str) { console.log(a); } 이터러블 / 이터레이터 프로토콜 for...of 문을 통해 Array, Set, Map 등 이터러블을 순회할 수 있다. 기존의 for...i++ 문은 Set과 Map을 순회하기가 어려웠다. // Array const arr = [1,2,3]; for (const a of arr) console.log

JavaScript 함수형 프로그래밍 - 제너레이터와 이터레이터 [내부링크]

제너레이터와 이터레이터 제너레이터 : 이터레이터이자 이터러블을 생성하는 함수 제너레이터를 실행한 결과는 이터레이터가 된다. 제너레이터로 생성한 이터레이터는 이터러블이기도 하다. 즉, 제너레이터로 생성한 이터레이터는 Symbol.iterator을 가지게 되고 well-formed iterator이다. 문장을 값으로 만들 수 있고 문장으로 통해 순회할 수 있는 값을 만들 수 있다. 즉, JS는 어떠한 문장이나 상태를 순회할 수 있는 상태로 만들 수 있다. function *get() { yield 1; yield 2; yield 3; if (false) yield 4; // done이 true일 때 value를 return으로 줄 수 있다. // 단, 순회할 때 return 값을 제외하고 순회한다. return 100; } let iter = gen(); console.log(iter[Symbol.iterator]() === iter); // true console.log(iter.ne

JavaScript 함수형 프로그래밍 - map [내부링크]

map 이터러블의 각 요소들에게 조건을 적용해 새로운 배열을 만드는 함수 const products = [ { name: '반팔티', price: 15000 }, { name: '긴팔티', price: 20000 }, { name: '핸드폰케이스', price: 15000 }, { name: '후드티', price: 30000 }, { name: '바지', price: 25000 }, ] const map = (f, iter) => { let res = []; for (const a of iter) { res.push(f(a)); } return res; }; map(p => p.name, products); map(p => p.price, products); 이터러블 프로토콜을 따른 map의 다형성1 Array의 내장 method인 map은 Array를 상속받은 경우 사용할 수 있다. // 에러가 발생한다 => Array가 아니기 때문이다. console.log(document.q

Zustand - Persist [내부링크]

용도 store에 데이터 유지 ex) import { create } from 'zustand' import { persist, createJSONStorage } from 'zustand/middleware' export const useBearStore = create( persist( (set, get) => ({ bears: 0, addABear: () => set({ bears: get().bears + 1 }), }), { name: 'food-storage', // name of the item in the storage (must be unique) storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used } ) ) option name 유일한 필수 옵션 store에 zustand 상태를 저장하는 데 사용되는 키 storage 자신의 저장소를 사용할

Zustand - Persist API [내부링크]

개념 React 구성 요소 내부 또는 외부에서 Persist 미들웨어와 다양한 상호 작용을 수행할 수 있다. 수화는 저장소에서 지속된 상태를 검색하여 현재 상태와 병합하는 프로세스입니다. Persist 미들웨어는 동기식과 비동기식의 두 가지 수화를 수행합니다. 주어진 저장소가 동기식이면(예: localStorage) 수화는 동기식으로 수행됩니다. 반면에 주어진 저장소가 비동기식(예: AsyncStorage)인 경우 수화는 비동기식으로 수행됩니다 공식문서 Zustand Documentation Zustand is a small, fast and scalable bearbones state-management solution, it has a comfy api based on hooks docs.pmnd.rs getOptions Persist 미들웨어의 옵션을 가져올 수 있다. useBoundStore.persist.getOptions().name setOptions 미들웨어 옵션을 변

D3 - circle pack 그래프 그리기 [내부링크]

pack은 계층구조의 그림을 그릴 수 있는 데이터를 생성합니다. 보통 circle pack으로 그림을 그립니다. 이를 위해 계층구조 데이터를 가공하는 메서드가 필요한데 그 메서드가 바로 hierarchy(하이어러키, 계층구조) 입니다. d3-hierarchy/README.md at v1.1.8 · d3/d3-hierarchy 2D layout algorithms for visualizing hierarchical data. - d3-hierarchy/README.md at v1.1.8 · d3/d3-hierarchy github.com d3.hierarchy()와 d3.stratify()는 계층 데이터를 가공합니다. 이렇게 만들어진 node은 each, ancestors, descendants 등에 메서드를 가집니다. each는 순회하며 각 노드에 속성을 적용할 때 사용합니다. ancestors는 조상 노드를 반환합니다. descendants는 정렬된 배열을 반환합니다. // 예시

D3 - tree 그래프 그리기 [내부링크]

d3-hierarchy/README.md at v1.1.8 · d3/d3-hierarchy 2D layout algorithms for visualizing hierarchical data. - d3-hierarchy/README.md at v1.1.8 · d3/d3-hierarchy github.com 코드 <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>D3</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <div class="canvas"></div> <script> const data = [

D3 - 지리 데이터 [내부링크]

1. 나라별 SVG 파일 Free SVG Maps - amCharts www.amcharts.com 2. SVG to GeoJSON SVG to GeoJSON Converter Online - MyGeodata Cloud Upload your SVG File and Convert Drag & Drop files here... Or browse files to convert Please note that your data will not be shared to anybody unless you do it yourself. Conversion from SVG to GeoJSON Upload your SVG data (widely used in software like InkScape, Adobe and HTML5) and convert them by ... mygeodata.cloud 3. 사용한 data 지리 정보는 22년 4월 data입니다. 면 -> 읍 승격 등 연마다 변하는 da

D3 - 상호작용 [내부링크]

이벤트를 적용할 수 있는 방법이다. <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>D3</title> <script src="https://d3js.org/d3.v7.min.js"></script> <style> .tooltip { position: absolute; text-align: center; padding: 10px; background: gray; color: white; border-radius: 3px; } h1 { position: absolute; height: 500px; width: 500px; } </style> </head> <body> <h1>hello wo

React-query : defaultOptions 지정하기 [내부링크]

index.tsx에서 react-query 초기 셋팅을 할 때 default 값을 지정하면 모든 query 에 해당 옵션이 기본적으로 적용된다. 만약 해당 옵션이 필요한 경우 query를 사용할 때 각각 지정해주면 된다. const queryClient = new QueryClient({ defaultOptions: { queries: { retry: 0, useErrorBoundary: true, suspense: true, refetchOnWindowFocus: false, keepPreviousData: true, }, mutations: { useErrorBoundary: true, retry: false, }, }, });

React - ErrorBoundry (class component 형태로 사용하기) with typescript [내부링크]

이전 프로젝트에서는 react-error-boundary 라이브러리를 사용하여 ErrorBoundary를 구현해보았다. 이번에는 React 공식문서에 나온 class 형태로 ErrorBoundary를 해 볼 생각이다. 공식문서 에러 경계(Error Boundaries) – React A JavaScript library for building user interfaces ko.legacy.reactjs.org TypeScript 코드 React 공식 문서에는 JS 형태의 코드가 나와있다. TypeScript를 사용하기 위해서는 해당하는 Type을 지정해주어야 한다. 아래의 코드는 기본적인 ErrorBoundary의 형태이다. import React, { ErrorInfo, ReactNode } from "react"; interface Props { children?: ReactNode; } interface State { hasError: boolean; } class ErrorB

Property 'textContent' does not exist on type 'EventTarget’ 에러 해결 [내부링크]

React 프로젝트를 진행하다 아래와 같은 에러를 발견했다. 이전과 동일하게 Event를 적용하고 Type을 지정해주었지만 처음보는 에러가 발생했다. 에러를 해결하기 위해 구글링을 해보니 간단한 해결법이 존재해 소개해주겠다. // onClick type을 지정해줬는데 에러가 발생했다. const viewContent = (e: React.MouseEvent<HTMLUListElement>) => { console.log(e?.target.textContent); }; onClick={viewContent} // 해결 const viewContent = (e: React.MouseEvent<HTMLUListElement>) => { console.log((e?.target as HTMLElement).textContent); }; onClick={viewContent} 이벤트의 target을 HTMLElement로 정의해주면 해당하는 오류가 사라진 것을 알 수 있다.

vscode - Vim 활용하기2 [내부링크]

입력모드 / 명령모드 // 입력모드로 전환하기 o ( 현재 커서 아래에 새로운 라인을 추가 후, 편집하겠다. ) O ( 현재 커서 위에 새로운 라인을 추가 후, 편집하겠다. ) // 선택기능 V [Shift + v] ( 현재 라인을 선택 - visual line ) // 지우기 dw ( 현재 커서부터 단어의 끝까지 지우기 ) D [Shift + d] ( 현재 커서의 뒤편 전부 삭제 ) // 작업 취소 ( undo ) U [Shitf + u] ( 해당 라인의 전체 수정사항을 취소 ) // 내용 변경 c$ ( 선택된 라인 삭제 후, 입력 ) // 이동 $ [Shift + 4] ( 현재 라인의 맨 뒤로 이동 ) ^ [Shift + 6] ( 현재 라인의 맨 앞으로 이동 ) 라인번호 + G ( 해당 라인으로 이동 ) // 저장하고 나가기 ZZ [Shift + zz] ( 현재 파일을 저장하고 vim 종료 / VS Code : ) * [Shift + 8] ( 현재 커서가 있는 해당 단어와 동일한

D3 - line 그래프 그리기 (실전 예시) [내부링크]

ine은 아래와 같이 x1과 y1, x2와 y2가 필요하다. 따라서 path로 그리도록 할 예정이다. d3.select('svg') .append('line') .attr('x1', 100) .attr('y1', 100) .attr('x2', 200) .attr('y2', 200) .style('stroke', 'black') .style('stroke-width', '2px') svg로 line을 그릴 수 있는 방법 1. line <line x1="100" y1="100" x2="200" y2="200"> 2. polyline <polyline points='100,100 200,200'> 3. path path에 관련된 내용은 좀 더 많아 mdn문서를 첨부합니다. 곡선을 그리는 것은 path밖에 되지 않습니다! <path d='M100 100 L200 200'> 참고 패스 - SVG: Scalable Vector Graphics | MDN <path> 엘리먼트는 SVG 기본 도형

D3 - 생성기 [내부링크]

생성기는 데이터를 입력받아 해당 객체를 그릴 수 있는 SVG 코드를 반환합니다. 문서 https://github.com/d3/d3-shape 종류 line() area() arc() line <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>D3</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <div class="canvas"> <svg> <path></path> <path></path> <path></path> <path></path> <path></path> <path></path> <path><

D3 - 컴포넌트 [내부링크]

화면에 표현될 수 있는 객체 생성(생성기는 svg안에 d값을 생성하는 것이고, 컴포넌트는 화면에 직접 들어가는 값을 생성합니다.) brush() - https://github.com/d3/d3-brush zoom() - https://github.com/d3/d3-zoom text() - axis() - https://github.com/d3/d3-axis D3의 공식 github → repositories에 들어가면 여러가지 컴포넌트와 예시코드를 볼 수 있다. 예시코드를 보면서 사용하는 것이 편하다. brush <body> <h1>확진자수 현황</h1> <div class="canvas"></div> <script> const width = 800 const height = 800 let [mt, mb, mr, ml] = [50, 50, 50, 50] const svg = d3.select('.canvas') .append('svg') .attr('width', width) .at

Zustand 시작하기 [내부링크]

1. 설치 npm install zustand # or yarn add zustand 2. store 생성 import { create } from 'zustand' const useBearStore = create((set) => ({ bears: 0, increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), removeAllBears: () => set({ bears: 0 }), })) 3. 컴포넌트에서 사용 const bears = useBearStore((state) => state.bears)

D3 - 산점도 그래프와 enter / exit [내부링크]

간단한 산점도 <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>D3</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <div class="canvas"></div> <script> // 코드의 복잡도를 올리지 않기 위해 아래와 같이 자동생성을 안한 것입니다. /* let sampleData = [] for (var i = 0; i < 1000; i++) { sampleData.push({ 'cx': Math.random() * 100, 'cy': Math.random() * 100, 'r': Math

D3 - 데이터 로드(csv, tsv) [내부링크]

csv 개념 콤마로 데이터 구분 CSV (파일 형식) - 위키백과, 우리 모두의 백과사전 CSV (파일 형식) 30개 언어 문서 토론 읽기 편집 역사 보기 도구 위키백과, 우리 모두의 백과사전. Comma-separated values Comma separated list 파일 확장자 .csv 인터넷 미디어 타입 text/csv [1] 포맷 종류 텍스트 표준 RFC 4180 CSV ( 영어 : comma-separated values )는 몇 가지 필드를 쉼표 (,)로 구분한 텍스트 데이터 및 텍스트 파일이다. 확장자는 .csv이며 MIME 형식 은 text/csv이다. comma-separated variables 라... ko.wikipedia.org csv 형태 출판연도,제목,매출(만원),순익(만원),가격(원) 2020,Python,300,10,1000 2021,HTML,310,20,2000 2022,CSS,320,30,3000 2023,JavaScript,330,40,4000

D3 - 데이터 로드(json, xml) [내부링크]

json 개념 속성과 값의 쌍으로 데이터 표현 JSON - 위키백과, 우리 모두의 백과사전 JSON 47개 언어 문서 토론 읽기 편집 역사 보기 도구 위키백과, 우리 모두의 백과사전. JSON ( 제이슨 [1] , JavaScript Object Notation )은 속성-값 쌍 (attribute–value pairs), 배열 자료형(array data types) 또는 기타 모든 시리얼화 가능한 값(serializable value) 또는 "키-값 쌍"으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다. 비동기 브라우저/서버 통신 ( AJAX )을 위해, 넓게는 ... ko.wikipedia.org 형태 [ { "지역이름": "전국", "확진자수": 24889, "격리해제수": 23030, "사망자수": 438, "십만명당발생율": 48.0, "지역별확진자비율": "" }, { "지역이름": "서울", "확진자수": 5607

vscode - Vim 활용하기 [내부링크]

입력모드 esc : 입력모드 나가기 i : 커서 앞으로 입력모드 a : 커서 뒤로 입력모드 I(대문자 i) : 현재 줄의 젤 앞에서 입력모드 A : 현재 줄의 젤 뒷부분에서 입력모드 명령모드 h,j,k,l : 왼쪽, 아래, 위, 오른쪽 방향키 0(숫자) : 현재 줄에서 젤 앞으로 가기 $ : 현재 줄에서 젤 뒤로가기 w(word) : 한 단어씩 앞으로 이동하기 n 단어씩 이동할려면 숫자를 입력한 뒤 w를 입력한다. ex) 3w : 3단어씩 이동 b(backword) : 한 단어씩 뒤로 이동하기 H: 화면 상에서 젤 위로 이동 L : 화면 상에서 젤 밑으로 이동 M : 화면 중간으로 이동 gg : 파일 앞으로 이동 G : 파일 끝으로 이동 숫자G : 특정한 줄로 이동 ex) 20G : 20번째 줄로 이동 ctrl u : 위로 스크롤링 ctrl d : 아래로 스크롤링 { : 문단 단위로 이동(시작) } : 문단 단위로 이동(끝) x : 현재 커서 아래 글자 삭제 dd : 문장 전체 삭제

안전지대 - 프로그래머스 [내부링크]

// 지뢰에 인접한 위, 아래, 좌, 우, 대각선은 모두 위험지역 // 지뢰는 2차원 배열 board에 1로 표시 // 지뢰가 없는 지역은 0으로 표시 // 안전한 지역의 칸 수를 return function solution(board) { // 8방향 탐색 const dr = [-1, -1, 0, 1, 1, 1, 0, -1]; const dc = [0, 1, 1, 1, 0, -1, -1, -1]; // 안전지대를 세는 변수 let cnt = Math.pow(board[0].length, 2); board.forEach((items, r) => { items.forEach((item, c) => { // 만약 지뢰를 찾으면 if (item === 1) { // 안전지대 갯수에서 1 감소 cnt -= 1; // 8방향 탐색 for (let i = 0; i < 8; i++) { let nr = r + dr[i]; let nc = c + dc[i]; // 방향이 범위를 벗어나지 않고 0이

D3 - 데이터 컨트롤 [내부링크]

데이터 컨트롤 데이터가 화면에 표시될 때 데이터 정규화 작업이 필요합니다. 예를 들어 대한민국 인구수를 연도별 바 그래프로 표현한다면 최대 인구수를 몇 px로 표현할지 정해야 하죠. 이렇게 크기를 변경하는 작업을 정규화라고 합니다. domain은 변환 전 값(실제 값)이고 range는 변환 후 값의 범위(범위 값)입니다. 문서에 시각화가 잘 되어 있으니 꼭 문서를 한 번씩 참고해주시기 바랍니다.(공식문서가 아닌 일반 노트인 경우가 많습니다.) scalePoint 간격에 맞게 값을 변경해줍니다. (x 축으로 많이 사용) d3.scalePoint / D3 | Observable config = ( { domain : [ "A" , "B" , "C" ] , // change me! padding : 0.6 , // round : true , // range : [ 40 , Math . min ( 700 , width - 40 ) ] // } ) scale = d3 . scalePo

D3 - bar 그래프 그리기 (실전 예시) [내부링크]

그래프를 그릴 공간을 정한다. <body> <h1>확진자수 현황</h1> <div class="canvas"></div> <script> const width = 800 const height = 800 let [mt, mb, mr, ml] = [50, 50, 50, 50] const svg = d3.select('.canvas') .append('svg') .attr('width', width) .attr('height', height ) </script> </body> 2. 그래프의 크기를 정한다. <body> <h1>확진자수 현황</h1> <div class="canvas"></div> <script> const width = 800 const height = 800 let [mt, mb, mr, ml] = [50, 50, 50, 50] const svg = d3.select('.canvas') .append('svg') .attr('width', width) .attr('he

삼각형의 완성 조건 - 프로그래머스 [내부링크]

// 가장 긴 변의 길이는 다른 두 변의 길이의 합보다 작아야한다. // 삼각형의 두 변의 길이가 담긴 배열이 매개변수 // 나머지 한 변이 될 수 있는 정수의 개수를 return function solution(slides) { // slides 내 최댓값 let currentMax = Math.max(...slides); // slides 내 최솟값 let currentMin = Math.min(...slides); // 추가로 들어오는 값 let extraNum = 1; // 결과 let result = 0; // 두 가지의 경우로 나눈다 // 1. slides 안에 있는 두 변 중 큰 값이 최대인 경우 while (extraNum <= currentMax) { if (currentMax >= extraNum + currentMin) { extraNum++; } else { extraNum++; result++; } } extraNum = currentMax + 1; // 2.

전화번호 하이픈 형식으로 변경하기 [내부링크]

정규표현식을 활용해 전화번호가 들어오면 하이픈 형식으로 변경해주는 함수를 작성해보았다. 프로젝트를 하면서 사용하기 유용한 것 같다. 입력된 문자열에서 숫자를 제외한 모든 문자를 제거한다. replaceAll 함수는 입력된 문자열에서 정규식과 일치하는 모든 문자를 찾아서 제거한다. 2. 입력된 전화번호 문자열의 길이를 확인한다. 3. 만약 전화번호가 8자리일 경우 앞, 뒤 4자리를 분리해서 '-'으로 구분된 문자열로 변환된다. replace 함수는 입력된 정규식과 일치하는 문자열을 찾아 첫 번째 그룹과 두 번째 그룹을 대체한다. $n : *n이 1이상 99이하의 정수라면, 첫번째 매개변수로 넘겨진 RegExp객체에서 소괄호로 묶인 *n번째의 부분 표현식으로 매치된 문자열을 삽입합니다. const usePhoneNum = (input) => { const cleanInput = input.replaceAll(/[^0-9]/g, ""); let result = ""; const lengt

네이버 맵 - Geocoder를 활용 주소와 좌표 검색 API 호출하기 [내부링크]

프로젝트를 진행하다가 지번주소와 우편번호가 필요한 경우가 있었다. 네이버 클라우드 플랫폼에 REST API 형식으로 데이터를 받을 수 있는 방법이 있었다. 분명 post-man으로 테스트 할 때는 데이터가 제대로 나왔지만 프론트에서는 CORS 에러가 발생했다. 그래서 다른 방법을 찾아보다가 geocoder 서브 모듈을 활용하여 주소를 받을 수 있는 방법이 있었다. 사용 예시 naver.maps.Service.geocode({ address: '불정로 6' }, function(status, response) { if (status !== naver.maps.Service.Status.OK) { return alert('Something wrong!'); } var result = response.result, // 검색 결과의 컨테이너 items = result.items; // 검색 결과의 배열 // do Something }); console에 items를 출력해보면 검색 결과가

React - CKEditor 사용하기 [내부링크]

설치 npm install --save @ckeditor/ckeditor5-react @ckeditor/ckeditor5-build-classic 2. 사용하기 기본 사용 예제 import React, { Component } from 'react'; import { CKEditor } from '@ckeditor/ckeditor5-react'; import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; class App extends Component { render() { return ( <div className="App"> <h2>Using CKEditor 5 build in React</h2> <CKEditor editor={ ClassicEditor } data="<p>Hello from CKEditor 5!</p>" onReady={ editor => { // You can store the "editor" and u

React - favicon 변경하기 [내부링크]

이미지를 ico 파일로 다운로드 한다. 프로젝트 폴더에 넣는다. favicon.ico 이름으로 변경한 뒤 폴더에 넣어준다. 3. index.html에서 추가해준다. <head> <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> </head>

D3의 개념과 도형 그리기 [내부링크]

동작 과정 Loading - 데이터 로딩 Selecting-Binding - 코드 연동 Transform - 그래프의 색상, 축 등 설정 Transition - 클릭 등의 효과 지정 기본메서드 d3.select : 태그 하나 선택(Selecting) - querySelector와 유사 d3.selectAll : 태그 전체 선택(Selecting) - querySelectorAll과 유사 .data : 데이터 로딩 .enter : 태그가 데이터에 비해 부족하면 데이터의 수만큼 태그 생성(부족한 태그를 생성후 반환) .append : 새로운 태그 추가 .exit : 태그가 데이터에 비해 많다면 나머지 태그 반환, 주로 태그 속성 지정을 종료하고 아래 remove로 나머지 태그 제거하는 용도로 사용 .remove : 선택된 태그 제거 도형그리기 svg태그 안에서 circle, rect 등 다양한 도형 제공 g태그는 그룹화 하는 용도로 사용합니다. 여러개의 그래프를 그릴 경우 여러개의 g태

SVG 개념 [내부링크]

SVG란? 확장 가능한 벡터 그래픽(scalable vector graphics)으로 XML 기반의 2차원 그래픽입니다. HTML 태그의 집합으로 이루어져 있습니다. 즉, css와 javascript로 컨트롤이 가능합니다. SVG의 장점 아무리 확대를 해도 이미지가 깨지지 않습니다. 또한, 이미지의 크기를 키워도 용량이 늘어나지 않습니다. SVG의 단점 코드로 이루어진 이미지이기 때문에 복잡한 이미지일수록 파일 사이즈가 커집니다. 단순한 모양일수록 효율이 좋습니다. 복잡한 이미지를 굳이 SVG로 표현하고자 하면 오히려 용량이 너무 거대해져 역효과가 날 수 있습니다. 그렇기 때문에 주로 단순한 아이콘, 로고, 도형 등을 구현할 때 많이 사용합니다. HTML에 SVG를 적용하는 방법들 이미지를 SVG로 변환해주는 사이트 https://convertio.co/kr/png-svg/ img 태그로 사용하기 (조작 불가) <img src="frog.svg" alt=""> css backgrou

D3 - 막대 그래프 그리기 [내부링크]

기본 <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>D3</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <svg width="500" height="500"></svg> <script> const sampleData = [100, 10, 30, 50, 10, 70, 200, 90]; const svg = d3.select('svg'); sampleData.forEach((data, index) =>{ svg.append('rect') .attr('height', data) .attr('width'

겹치는 선분의 길이 - 프로그래머스 [내부링크]

// 세 선분의 시작과 끝 좌표가 2차원 배열로 주어진다. // 두 개 이상의 선분이 겹치는 부분의 길이를 return function solution(lines) { // 겹치는 범위를 저장하는 객체 const resultObj = {}; // 결과값 let result = 0; // 순회할 때 시작값과 끝값 let start; let end; // 2차원 배열을 순회하면서 범위를 체크한다. lines.forEach((line) => { start = line[0]; end = line[1]; // 시작값과 끝값이 같으면 반복을 종료한다. while (start !== end) { // 객체에 범위가 존재하지 않으며 1로 초기화 존재하면 1을 증가시킨다. if (!resultObj[[start, start + 1]]) { resultObj[[start, start + 1]] = 1; } else { resultObj[[start, start + 1]]++; } start += 1;

평행 - 프로그래머스 [내부링크]

// 점 네 개의 좌표를 담은 이차원 배열 dots가 매개변수로 주어짐 // 주어진 네 개의 점을 두 개씩 이었을 때 // 평행이 되는 경우가 있으면 1 없으면 0을 return // 두 직선이 겹치는 경우에도 1을 return function solution(dots) { // 평행한 직선은 기울기가 동일하다. const dotsIdx = [0, 1, 2, 3]; let result = 0; // 기울기를 계산하는 함수 function calFnc(index1, index2) { const lean1 = Math.abs(dots[index1[0]][1] - dots[index1[1]][1]) / Math.abs(dots[index1[0]][0] - dots[index1[1]][0]); const lean2 = Math.abs(dots[index2[0]][1] - dots[index2[1]][1]) / Math.abs(dots[index2[0]][0] - dots[index2[1]]

React Event - onFocus, onBlur [내부링크]

프로젝트를 진행하면서 input 태그에 작성한 value 값을 가져오는 일이 많았다. 이때 주로 onChange 이벤트를 사용해 value가 변할때마다 값을 가져왔는데 불필요한 호출이 많다고 생각이 들어 다른 이벤트를 찾아보았다. 그러던 중 JS에서 focusOut 이벤트가 react에서는 onBlur 이벤트로 사용하고 있다는 사실을 알게되어 focus와 blur의 차이점을 공부했다. onFocus 엘리먼트가 포커스 될 때 호출된다. ex) <input onFocus={() => console.log('focus'} /> onBlur 엘리먼트에서 포커스가 사라졌을 때 호출된다. ex) <input onBlur={() => console.log('blur'} /> 느낀점 항상 onChange를 사용해 input의 변화를 감지했는데 매번 이벤트가 호출돼 불필요하다는 생각이 들었었다. 하지만 onBlur 이벤트를 사용하니 input에서 나오면 value 값을 가져와 많은 호출을 줄일 수

JavaScript 숫자 3자리마다 콤마 찍기 [내부링크]

가격을 표시하거나 큰 단위의 숫자를 표시할 때 3자리마다 콤마를 찍어서 표현하는 경우가 생깁니다. 이때 사용할 수 있는 방법을 소개하겠습니다. 1. 정규표현식 이용하기 const num = 123456; const newNum = num.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ","); 2. toLocaleString() 메서드 이용하기 number.toLocaleString(locales, options) 로컬의 language format에 맞는 문자열로 변경해준다. 파라미터로 아무것도 전달되지 않으면 사용자 로컬 환경의 locale을 default로 사용한다. const num = 123456; const newNum = num.toLocaleString('ko-KR');

Dialog 태그로 modal 만들기 [내부링크]

1. 기본적인 형태 // html <button>Show modal</button> <dialog> Hello! I'm a modal! </dialog> // js const button = document.querySelector('button'); const dialog = document.querySelector('dialog'); // 버튼을 클릭하면 modal이 보여진다. button.addEventListener('click', () => { dialog.showModal(); }) // react-version const buttonRef = useRef(); const onClick = () => { buttonRef.current.showModal(); } <button onClick={onClick}>Show modal</button> <dialog ref={buttonRef}> Hello! I'm a modal! </dialog> 기본적으로 modal이 열린 상태

저주의 숫자 3 - 프로그래머스 [내부링크]

// 3의 배수와 숫자 3을 사용하지 않는다. // 정수 n이 주어질 때 3x 마을에서 사용하는 숫자로 바꿔 return function solution(n) { // 3이 아닌 수를 세는 변수 let count = 0; // 3x 마을의 숫자 let three = 1; // 3이 있는지 확인하는 정규 표현식 const regExp = /3/; while (count !== n) { if (regExp.test(three)) { three++; } else if (!(three % 3)) { three++; } else { count++; three++; } } return three - 1; } console.log(solution(40)); 처음에 정규 표현식을 /3/g를 사용했는데 이렇게 하니 31부터 조건을 만족하지 못해서 /3/으로 정규 표현식을 수정했다. 오랜만에 정규표현식을 사용해서 조금 헷갈렸다.

외계어 사전 - 프로그래머스 [내부링크]

// 알파벳이 담긴 배열 spell과 외계어 사전 dic이 매개변수 // spell에 담긴 알파벳을 한번씩만 모두 사용한 단어가 // dic에 존재하면 1, 아니면 2를 return function solution(spell, dic) { for (let i of dic) { let cnt = 0; for (let j of spell) { if (!i.includes(j)) { break; } cnt++; } if (cnt === spell.length) { return 1; } } return 2; } console.log(solution(["z", "d", "x"], ["def", "dww", "dzx", "loveaw"])); 사전에 있는 단어를 순회하면서 해당 단어에 spell이 존재하면 cnt를 1 증가시키고 존재하지 않으면 바로 반복문을 빠져나오게 했다. 그래서 cnt가 spell의 길이와 동일하면 바로 1을 return하고 만약 끝까지 return이 되지 않았으면 존재하

0.1 파이썬(변수, 식별자, 자료형) [내부링크]

0.1.1 변수 변수는 데이터를 담는 상자를 의미한다. 데이터를 저장하기 위해서 사용한다. 변수를 사용하면 복잡한 값들을 쉽게 사용할 수 있다. (추상화) 동일 변수에 다른 데이터를 언제든 할당(저장) 할 수 있다. 0.1.2 식별자 (변수 이름 규칙) 첫 글자에 숫자가 올 수 없다. 대, 소문자를 구분해야 한다. keywords는 예약어로 사용이 불가능하다. 'False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield' 내장 함수나 모듈 등의 이름도 사용이

JS 알고리즘 24일차 - 동적 프로그래밍 [내부링크]

동적 프로그래밍 정의 복잡한 문제를 더 간단한 하위 문제의 모음으로 쪼개서 각 하위 문제들을 풀어서 그 답을 저장하는 방식으로 문제를 푸는 방법 언제 동적 프로그래밍을 사용하는가? 동적 프로그래밍을 사용할 수 있는지를 확인하기 위해서는 두 가지를 확인해야 한다. 최적 부분 구조가 존재하는지 여부 반복되는 하위 문제가 있는지 여부 예시 function fib(n) { if (n <= 2) return 1; return fib(n-1) + fib(n-2); } 단점 시간복잡도가 O(2^n)이라서 많이 느리다. Memo에 값을 저장하는 방법 반복되는 하위 문제에 대한 답을 저장하는 방법 예시 function fib(n, memo=[]) { if (memo[n] !== undefined) return memo[n]; if (n <= 2) return 1; let res = fib(n-1,memo) + fib(n-2, memo); memo[n] = res; return res; } 시간 복잡

emotion.js 조건부 스타일 적용 [내부링크]

기본적인 사용법 import를 한다. 스타일을 작성한 뒤 변수에 할당한다. 요소에 적용한다. 예시 코드 // 1번 /** @jsxImportSource @emotion/react */ import { css } from "@emotion/react"; // 2번 const toggleBtn = css` list-style: none; margin: 3% 0 0 0; padding: 0; border: 0; border-top: #555555 2px solid; display: flex; position: sticky; top: 0; background-color: #fafafa; cursor: pointer; li { flex: 1; border: 1px solid #cccccc; text-align: center; height: 4vh; display: flex; align-items: center; justify-content: center; font-weight: 900; fo

.env 파일로 API 키 안전하게 보관하 [내부링크]

1. 폴더 최상위에 .env 파일을 생성한다. 2. .gitignore에 .env를 추가해서 git에 올라가지 않도록 한다. 3. 그 다음 API key들을 적어준다. 반드시 REACT_APP으로 시작해야 하고 =으로 빈칸 없이 적어준다. env 설정 후 서버를 한 번 끄고 실행한다. 4. 사용할 때는 process.env.REACT_APP_이름에 변수를 할당하여 사용한다. html에서는 %REACT_APP_이름% 이렇게 넣어주면 끝이다. 5. typescript를 사용할 때는 tsconfig.json을 수정해준다. 6. process의 타입을 지정해주면 자동완성도 가능하다.

onClick target - target과 currentTartget의 차이 [내부링크]

이벤트 버블링은 e.stopPropagation을 사용하면 간단하게 해결할 수 있다. 반대로 클릭했을 때 부모 요소를 출력하고 싶을 때는 어떻게 해야할까??? e.target 부모 요소로부터 이벤트가 위임되어 실제 이벤트가 발생한 자식 요소를 가리킨다. 즉, 직접적으로 클릭한 요소 e.currentTarget 내가 click 이벤트를 걸어놓은 요소를 직접적으로 가리킨다.

네이버 맵 API - 파노라마 생성 [내부링크]

참고 NAVER Maps API v3 NAVER Maps API v3로 여러분의 지도를 만들어 보세요. 유용한 기술문서와 다양한 예제 코드를 제공합니다. navermaps.github.io 시작 아래의 스크립트를 적용시킨다. YOUR_CLIENT_ID에는 발급받은 key를 넣는다. <script type="text/javascript" src="https://openapi.map.naver.com/openapi/v3/maps.js?clientId=YOUR_CLIENT_ID&submodules=panorama"></script> 요소 생성 파노라마를 생성할 요소를 하나 만든다. 선택한 요소에 파노라마를 적용한다. const roadViewRef = useRef<HTMLDivElement | null>(null); var pano = new naver.maps.Panorama(roadViewRef.current, panoramaOptions); <div css={roadView} ref

View Transitions API [내부링크]

페이지간 전환에 애니메이션 효과를 줄 수 있다. 사용 예시 // index.html <meta name="view-transition" content="same-origin" /> <body> <a href-"dog.html">Look at my dog</a> </body> // dog.html <meta name="view-transition" content="same-origin" /> <body> <h1>She is the best!</h1> </body> 애니메이션 커스텀 // 이전 페이지가 사라질 때, 애니메이션 커스텀 ::view-transition-old(root) // 새 페이지가 사라질 때, 애니메이션 커스텀 ::view-transition-new(root) 사용 예시 // index.html <meta name="view-transition" content="same-origin" /> <style> ::view-transition-old(root), ::view-

CSS를 활용한 부드러운 스크롤 이동 [내부링크]

html { scroll-behavior: smooth; } 전체 코드 // html 코드 <!DOCTYPE html> <html lang="en"> <head> <title>상세 페이지</title> </head> <link rel="stylesheet" href="style.css" /> <body> <div class="wrap"> <main> <div class="product__top">상품 상세설명</div> <nav class="tap"> <ul> <li><a href="#tap1">상품상세</a></li> <li><a href="#tap2">상품평</a></li> <li><a href="#tap3">상품문의</a></li> <li><a href="#tap4">배송/교환/반품 안내</a></li> </ul> </nav> <div id="tap1" class="tab__content">상품상세 내용</div> <div id="tap2" class="tab__content"

CSS 가상요소 - before, after [내부링크]

대표적으로 사용되고 있는 가상요소 요소 소개 ::first-line 요소의 텍스트에서 첫 줄에 스타일을 적용한다. ::first-letter 요소의 첫 번째 글자에 스타일을 적용한다. ::before 요소의 콘텐츠 시작부분에 생성된 콘텐츠를 추가한다. ::after 요소의 콘텐츠 끝부분에 생성된 콘텐츠를 추가한다. ::selection 요소의 텍스트에서 사용자에 의하여 선택(드래그)된 영역의 속성을 변경한다. ::placeholder input 필드에 힌트 텍스트에 스타일을 적용한다. ::before 실제 내용 바로 앞에서 생성되는 자식 요소 ::after 실제 내용 바로 뒤에서 생성되는 자식 요소 content before과 after를 사용할 때는 무조건 content라는 속성이 필요하다. content는 가짜 속성을 의미한다. HTML 문서에 정보로 포함되지 않는 요소를 CSS에서 새롭게 생성시켜주기 때문이다. content를 사용할 때 사용되는 대표적인 속성들 속성 사용 no

JS 알고리즘 23일차 - 다익스트라(Dijkstra) [내부링크]

가중치 그래프 일발 그래프에서 가중치를 추가로 넣어주면 된다. class WeightedGraph { constructor() { this.adjacencyList = {}; } addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList = []; } addEdge(vertex1, vertex2, weight) { this.adjacencyList[vertex1].push({node:vertex2, weight}); this.adjacencyList[vertex2].push({node:vertex1,weight}) } } 다익스트라 알고리즘 소개 시작점에서 출발해 새로운 노드에 방문을 한다. 가장 작은 거리 값을 가진 노드를 골라서 먼저 방문한다. 방문한 노드의 인접한 점들을 보면서 각각에 대해 A에서 해당 인접점까지의 거리를 함을 내어 구한다. 우리가 현재 알고 있는 것보다 더 적은 거리 값이 나오면 최신화 해준

ErrorBoundary를 활용한 에러 처리 [내부링크]

공식문서에서 에러 처리는 class 형태로 작성되어있다. 하지만 hook을 이용할 때에는 사용하기가 불편하다. class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // 다음 렌더링에서 폴백 UI가 보이도록 상태를 업데이트 합니다. return { hasError: true }; } componentDidCatch(error, errorInfo) { // 에러 리포팅 서비스에 에러를 기록할 수도 있습니다. logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // 폴백 UI를 커스텀하여 렌더링할 수 있습니다. return <h1>Something went wrong.</h

react-responsive-carousel 라이브러리를 활용한 carousel [내부링크]

차량 이미지를 보여줄 때 캐러샐을 사용해 보여줄 생각이었다. 처음에는 직접 캐러샐을 만들어 사용할 생각이었지만 프로젝트 시간이 부족해 라이브러리를 사용하기로 했다. 이번에 사용한 라이브러리는 react-responsive-carousel이다. // 설치 npm i react-responsive-carousel // 사용 // 두 가지를 모두 import해야 정상적인 캐러샐이 보인다. import { Carousel } from "react-responsive-carousel"; import "react-responsive-carousel/lib/styles/carousel.min.css"; <Carousel> <div> <img src={file} alt="qwe" /> <p className="legend">캐러샐에 들어갈 텍스트</p> </div> <div> <img src={file} alt="qwe" /> <p className="legend">캐러샐에 들어갈 텍스트</p>

Type 'any[] | undefined' must have a 'Symbol.iterator' method that returns an iterator 에러 해결 [내부링크]

문제 React 프로젝트를 진행하던 중 아래의 에러가 발생하였다. 처음에는 null 혹은 undefined가 될 수 있어 발생한 에러라고 생각했지만 잘 해결되지 않았다. 찾아보니 초기값이 없어서 발생한 에러라고 되어있었다. 해결 처음에 useState에 빈 값을 넣어도 해결되지 않아 OR 연산자를 이용해 빈 배열을 추가해주었다.

Naver map API (with react) [내부링크]

공식문서 NAVER Maps API v3 NAVER Maps API v3로 여러분의 지도를 만들어 보세요. 유용한 기술문서와 다양한 예제 코드를 제공합니다. navermaps.github.io 시작하기 1) NAVER CLOUD PLATFORM을 가입하고 API 사용요청을 한다. web domain 주소를 등록해야 사용할 수 있다. 2) index.html에 script를 넣는다. clientID는 발급받은 ClientID를 넣으면 된다. 3) Map을 띄울 컴포넌트를 만든다. React를 사용해 useRef로 div를 선택하였다. 4) 기본 마커 여러개 생성 단일 마커를 생성할려면 forEach문을 빼고 사용하면 된다. 5) 마커 위치 변경하는 방법 1. MarkerOptions의 position을 사용하여 마커 위치 변경 var markerOptions = { // 90도 위치(동쪽)에서 20미터만큼 이동 position: position.destinationPoint(90, 2

Gitlab에서 Github으로 commit log 유지하면서 옮기기 - 미러링 [내부링크]

원본 저장소를 복사한다. (github으로 옮길 원본 repository 주소) git clone --mirror [원본 레포지토리 경로] 2. 해당 폴더 안으로 들어간다. cs [원본 저장소 이름].git or 폴더 안으로 들어가서 다시 gitbash를 실행한다. 3. github repository를 하나 생성한 뒤 생성된 repository 주소를 넣는다. (이동할 원격 저장소 경로) git remote set-url --push origin [이동할 원격 레포지토리 주소] 4. push git push --mirror 5. 참고 github은 50MB가 넘어가면 올라가지 않는다. 이럴 때는 git lfs를 설치하여 올리면 된다.

React Router 기본 셋팅 [내부링크]

설치 npm install react-router-dom // 6버전 npm install react-router-dom v6 //typescript npm i react-router-dom @types/react-router-dom 2. 구성 // app.tsx import React from "react"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import Test from "./routes/Test"; function App() { return ( // <div className="App"></div> <Router> <Routes> <Route path="/" element={<Test />}></Route> </Routes> </Router> ); } export default App;

타입스크립트 useState Props하는 방법 [내부링크]

// useState의 타입을 정해준다. export interface RegistrationInfo { manufacturingCompany: string; carNumber: string; carYear: string; DistanceDriven: string; AdditionalSubmissionFiles: string; } // useState를 정의한다. const [registrationInfo, setRegistrationInfo] = useState<RegistrationInfo>({ manufacturingCompany: "", carNumber: "", carYear: "", DistanceDriven: "", AdditionalSubmissionFiles: "", }); // AdditionalSubmissionFiles라는 하위 컴포넌트에 props를 지정한다. <AdditionalSubmissionFiles setRegistrationInfo={setRegis

React에서 img 파일 보내기 [내부링크]

import axios from "axios"; import { useState } from "react"; import { useQuery } from "react-query"; import { RegistrationInfo } from "../../routes/MyVehicleRegistration"; interface Props { setRegistrationInfo: React.Dispatch<React.SetStateAction<RegistrationInfo>>; } // 허용가능한 확장자 목록! const ALLOW_FILE_EXTENSION = "jpg,jpeg,png"; const FILE_SIZE_MAX_LIMIT = 5 * 1024 * 1024; // 5MB function AdditionalSubmissionFiles({ setRegistrationInfo }: Props) { const fileList: File[] = []; // 업로드한 파일들을 저장하는 배

JS 알고리즘 21일차 - 해시 테이블 [내부링크]

정의 해시 테이블은 key값이 정렬되어 있지 않다. 값을 찾거나, 새로운 값을 추가하거나, 값을 제거하는데 아주 빠르다. 해시 테이블은 많이 사용되고, 데이터 그 자체가 이 방법에 따라 저장되는 것이 편한 경우가 많다. 같은 인풋이 들어가면 동일한 결과가 도출되어야 한다. 첫 번째 해쉬함수 작성하기 function hash(key, arrayLen) { let total = 0; for (let char of key) { let value = char.charCodeAt(0) - 96; total = (total + value) % arrayLen; } return total; } 해시함수 성능 향상시키기 소수를 사용해서 충돌을 피한다. function hash(key, arrayLen) { let total = 0; let WEIRD_PRIME = 31; for (let i = 0; i < Math.min(key.length, 100); i++) { let char = key[i]

React에서 img 미리보기 적용하기 [내부링크]

이전 포스팅에서 React에 img를 백엔드로 보내는 코드를 작성해보았다. 이번에는 이미지를 전송하기 전 사용자가 자신이 올린 이미지를 미리 볼 수 있도록 코드를 작성해보겠다. 코드 // 이미지를 넣는 코드에 추가 reader.onload = () => { setRegistrationInfo((registrationInfo) => { const newFileListL: any = [ ...registrationInfo.fileList, reader.result, ]; return { ...registrationInfo, fileList: newFileListL, }; }); }; reader.readAsDataURL(uploadFile); reader을 console에 찍어보면 base64로 변환된 이미지가 나온다. 이 데이터를 img 태그에 적용하면 이미지가 보인다. // 사용 <img src={registrationInfo?.fileList[0]} alt="Thumnail" wi

React - typescript에서 파일 import [내부링크]

(1) @types/global/index.d.ts 생성 프로젝트 디렉토리 root레벨에 @types/global/index.d.ts 폴더 및 파일을 생성한다. (2) index.d.ts 작성 생성한 폴더에 .d.ts 형식의 파일을 하나 생성해준다. 필자는 index.d.ts라는 파일을 생성했다. 그 다음 안에 허용할 확장자를 적어준다. declare module "*.gif"; declare module "*.png"; (3) tsconfig.json tsconfig.json - compilerOptions 안에 밑의 내용을 작성해주자."typeRoots": ["./node_modules/@types", "@types"]

JS 알고리즘 21일차 - 그래프(Graphs) [내부링크]

소개 그래프는 유한하고 변할 수 있는 꼭지점이나 노드나 점들의 집합으로 구성된 데이터 구조이다. 꼭지점들의 집합에 순서가 없는 경우에는 무방향 그래프, 순서가 있는 경우에는 유방향 그래프라고 한다. 용어 정점 : 노드를 이르는 다른 말 간선 : 노드 사이의 연결을 의미 기중 / 비가중 비가중 그래프는 노드 또는 정점 사이에 존재하는 연결인 간선에 부여된 값이 없다. 가중 그래프는 간선에 값이 부여되어 있다. 방향 / 무방향 무방향 그래프에는 방향이나 양극, 음극 같은 것이 없다. 즉, 양방향 연결이 되어있는 셈이다. 방향 그래프는 보통 방향을 의미하는 화살표로 표현이 된다. 해당 간선의 극성이라고 봐도 좋다. 그래프 정렬 : 인접 행렬 2차원 행렬로 각 노드들의 연결 상태를 나타낸다. 그래프 정렬 : 인접 리스트 배열이나 객체 형태로 해당 노드에 어떤 노드가 연결되어 있는지를 나타낸다. 인접 행렬 VS 연결 리스트의 시간 복잡도 V는 노드의 수, E는 간선의 수 간선이 많지 않고 퍼

JS 알고리즘 22일차 - 그래프 탐색(BFS, DFS) [내부링크]

깊이 우선 그래프 순회 - DFS 재귀형 의사코드 DFS라는 메소드를 만든다. 이 메소드는 시작 정점 하나를 받는다. return 조건을 설정한다. return 조건에 부합하지 않으면 해당 정점을 방문했단 표시는 남긴다. 그 다음 해당 정점과 인접한 정점을 확인한다. 인접한 정점이 방문하지 않았다면 재귀를 통해 다시 반복한다. 코드 지난 시간에 작성했던 graph 클래스의 추가하여 작성하였다. class Graph { constructor() { this.adjacencyList = {} } depthFirstRecursive(start) { const result = []; const visited = {}; const adjavencyList = this.adjacencyList; (function dfs(vertex) { if (!vertex) return null; visited[vertex] = true; result.push(vertex); adjacencyList[ver

useRef Dom 요소 여러개 선택하기 [내부링크]

무한 스크롤을 구현하다 useRef로 요소를 선택해야 했다. 그래서 찾아보니 이 방식으로 하면 요소를 여러개 선택할 수 있었다. 1. 객체로 ref를 생성 const divRef = useRef<HTMLDivElement | any>({}); 2. 반복되는 객체에 ref를 선언한뒤 함수 형태로 작성 {data?.pages[0].data.map((page: Page, index: number) => { return ( <div css={infoBox} key={index} ref={(ref) => (divRef.current[index] = ref)} > </div> 3. ref를 console에 입력하면 여러개가 들어가있다.

infinityQuery와 intersectionObserver를 활용한 React 무한 스크롤 [내부링크]

import axios from "axios"; import { useInfiniteQuery } from "react-query"; import carImg from "../../assets/car.png"; import { useEffect, useLayoutEffect, useRef } from "react"; // 타입 모음 interface Page { body: string; email: string; id: number; name: string; postId: number; } interface PageParam { pageParam?: number; } // infinityQuery 콜백함수 function infinityFnc({ pageParam = 1 }: PageParam) { return axios({ method: "get", url: `https://jsonplaceholder.typicode.com/comments`, params: { postId: pa

Overloading 활용하기 [내부링크]

function shuffle<T extends string | any[]>(value: T): T extends string? string : T; function shuffle(value: any) { if (typeof value === 'string') { return value.split('').sort(() => Math.random()-0.5).join(''); } return value.sort(() => Math.random() - 0.5); } shuffle('Hello, Mark'); // string shuffle(['a','b','c']) // string[] shuffle([1,2,3,4,5]) // number[] shuffle(1) // error

readonly, as const [내부링크]

class Layer { id!: string; name!: string; x: number = 0; y: number = 0; width: number = 0; height: number = 0; } const LAYER_DATA_INITIALIZE_INCLUDE_KEYS: ReadonlyArray<keyof Layer> = [ 'x', 'y', 'width', 'height' ]; const x = LAYER_DATA_INITIALIZE_INCLUDE_KEYS[0]; // "id" | "name" | "x" | "y" | "width" | "height"; const LAYER_DATA_INITIALIZE_EXCLUDE_KEYS = ["id", "name"] as const; const id = LAYER_DATA_INITIALIZE_EXCLUDE_KEYS[0]; // "id" ReadonlyArray<T> const weekdays: ReadonlyArray<string> =

Conditional Type을 활용하기(1) [내부링크]

1. Generic을 활용해 T에 따라 달라지는 container interface StringContainer { value: string; format(): string; split(): string[]; } interface NumberContainer { value: number; nearestPrime: number; round(): number; } type Item<T> = { id: T; container: T extends string ? StringContainer : NumberContainer; }; const item1: Item<string> = { id: 'aaaaa', container: null // Type 'null' is not assignable to type 'StringContainer' } // T가 string이면 StringContainer, number이면 NumberContainer, 아니면 사용 불가 type Item2<T> = {

Conditional Type을 활용하기(2) [내부링크]

2. 함수의 리턴 타입 알아내기 function plus1(seed: number): number { return seed + 1; } type MyReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any type Id = MyReturnType<typeof plus1>; lookupEntity(plus1(10)); function lookupEntity(id: id) { // query DB for entity by ID }

Class를 안전하게 만들기 [내부링크]

1. class Square1 { area; // error! implicit any, any면 명시해주거나 다른 타입을 넣어야한다. sideLength; //error! implicit any } 2. // 명시한 뒤 compile에는 number지만 runtime에는 undefined라 에러가 발생한다. class Square2 { area: number; sideLength: number; } const square2 = new Square2(); console.log(square2.area); // compile time - number, runtime - undefined console.log(square2.sideLength); // compile time - number, runtime - undefined 3. strictPropertyInitialization 옵션을 킨다. class Square2 { area: number; // error sideLength: n

서브타입과 슈퍼타입 [내부링크]

서브타입과 슈퍼타입 같거나 서브 타입인 경우 할당이 가능하다. ⇒ 공변 함수의 매개변수 타입만 같거나 슈퍼타입인 경우 할당이 가능하다. ⇒ 반병 // sub1 타입은 sup1 타입의 서브 타입이다. // sup1 타입은 sub1 타입의 슈퍼 타입이다. let sub1: 1 = 1; let sup1: number = sub1; sub1 = sup1 // 에러 // sub2 타입은 sup2 타입의 서브 타입이다. // sup2 타입은 sub2 타입의 슈퍼 타입이다. let sub2: number[] = [1]; let sup2: object = sub2; sub2 = sup2 // 에러 // sub3 타입은 sup3 타입의 서브 타입이다. // sup3 타입은 sub3 타입의 슈퍼 타입이다. let sub3: [number, number] = [1,2]; let sup3: number[] = sub3; sub3 = sup3 // 에러 // sub5 타입은 sup5 타입의 서브 타입이다.

타입 추론하기 [내부링크]

기본적인 타입 추론 let a = 'Mark'; // string const b = 'Mark' // 'Mark' => literal type let g = ['Mark', 'Haeun']; // string[] const h = ['Mark', 'Haeun']; // string[] const i = ['Mark', 'Haeun'] as const; // readonly ['Mark', 'Haeun'] Best common type let j = [0,1,null]; // (number | null)[] const k = [0,1,null]; // (number | null)[] class Animal {} class Rhino extends Animal {} class Elephant extends Animal {} class Snake extends Animal {} let i = [new Rhino(), new Elephant, new Snake()]; // (Rhino |

Type Guard로 안전함을 파악하기 [내부링크]

1. typeof Type Guard - 보통 Primitive 타입일 경우 function getNumber(value: number | string): number { value; // number | string if (typeof value === 'number') { value; //number return value; } value; // string return -1; } 2. instanceof Type Guard // 일반적인 예제 interface IMachine { name: string; } class Car implements IMachine { name: string; wheel: number; } class Boat implements IMachine { name: string; motor: number; } function getWhellOrMotor(machine: Car | Boat): number { if (machine instanceof Car)

유틸리티 타입 [내부링크]

// keyof interface User { id: number; name: string; age: number; gender: "m" | "f"; } type UserKey = keyof User; // 'id' | 'name' | 'age' | 'gender' 이랑 똑같다. =============================================================================== // Partial<T> : 프로퍼티를 모두 옵션으로 바꾸어준다. 따라서 일부만 사용할 수 있다. interface User { id: number; name: string; age: number; gender: "m" | "f"; } let admin: User = { id:1, name: 'Bob' } // 에러가 발생한다. let admin2: Partial<User> = { id:1, name: 'Bob' } // 에러가 사라진다. ===============

타입스크립트 컴파일 옵션 [내부링크]

nolmplicitAny 타입을 명시적으로 지정하지 않은 경우 타입스크립트가 추론 중 ‘any’라고 판단하게 되면, 컴파일 에러를 발생시켜 명시적으로 지정하도록 유도한다. strictNullChecks 모든 타입에 자동으로 포함되어 있는 ‘null’과 ‘undefined’를 제거해준다. nolmplicitReturns 함수 내에서 모든 코드가 값을 리턴하지 않으면, 컴파일 에러를 발생시킨다. strictFunctionTypes 함수의 매개변수 타입만 같거나 슈퍼타입인 경우가 아닌 경우, 에러를 통해 경고한다. strictPropertyInitialization Class의 Property가 생성자 혹은 선언에서 값이 지정되지 않으면, 컴파일 에러를 발생시켜 주의를 준다. 추가적인 컴파일 옵션보기 https://typescript-kr.github.io/pages/compiler-options.html TypeScript 한글 문서 TypeScript 한글 번역 문서입니다 typesc

Generic [내부링크]

클래스나 함수, 인터페이스를 다양한 타입으로 재사용할 수 있다. 선언할 때는 타입 파라미터만 작성한 뒤 생성하는 시점에 타입 파라미터를 결정 Generic을 사용할 때 특정한 타입을 입력하지 않아도 자동으로 처리한다. 그래서 특정 타입으로 강제하고 싶을 때에만 작성해도 무방하다. function getSize(arr:number[]):number { return arr.length; } const arr1 = [1,2,3]; getSize(arr1); //3 const arr2 = ["a", "b","c"]; getSize(arr2); // 에러가 발생한다. 함수 오버로드를 사용하거나 유니온 타입을 사용해야한다. // generic을 사용하는 방법 function getSize<T>(arr:T[]):number { return arr.length; } const arr1 = [1,2,3]; getSize<number>(arr1); //3 const arr2 = ["a", "b","c

TypeScript 기본 타입 [내부링크]

// 문자열 타입 let car:string = 'bmw'; // 숫자 타입 let age:number = 30; // 불리언 타입 let isAdult:boolean = true; // 배열 (숫자) let a:number[] = [1,2,3]; let b:Array<number> = [1,2,3]; // 배열 (문자열) let week1:string[] = ['mon', 'tue', 'wed']; let week2:Array<string> = ['mon', 'tue', 'wed']; // 튜플 (Tuple) : 인덱스 별로 타입이 다를 때 이용할 수 있다. let b:[string, number]; // 배열의 첫 번째 요소는 string, 두 번째 요소는 number // void : 함수에서 아무것도 반환하지 않을 때 사용한다. function sayHello():void { console.log('hello') } // never : 항상 에러를 반환하거나 영원히 끝나지 않

인터페이스 [내부링크]

interface는 merging을 할 수 있다. type alias에서는 사용할 수 없다. interface Test { a: string; } interface Test { b: string; } let test: Test; // test.을 하면 a와 b가 둘다 나온다. 프로퍼티를 정의해서 객체로 표현하고자 할 때 type Score = 'A' | 'B' | 'C' | 'F'; interface User { name :string; age: number; // 입력을 해도 되고 안해도 되는 속성에는 ?를 붙인다. gender? : string; // 읽기 전용 속성으로 만들면 수정시 에러가 발생한다. 즉 최소 생성시만 할당이 가능. readonly birthYear: number; // 문자열 인덱스 서명, grade는 의미가 없다. 이름일 뿐이다. // key가 number이고 value가 string인 프로퍼티를 여러 개 받을 수 있다는 의미. [grade: number]

함수 타입 정의 [내부링크]

// 선택적 매개변수를 주어 선택적으로 사용할 수 있다. function hello(name?:string):string { return `Hello, ${name || "world"}` } const result = hello(); // undefined 가능 const result2 = hello("sam"); // default 값을 줄 수 있다. function hello2(name = "world"):string { return `Hello, ${name}` } // 선택적 매개변수가 필수 매개변수보다 앞에 오면 에러가 발생한다. function hello(age?: number, name: string) :string { if (age !== undefined) { return 'Hello'; } else { return 'hello'; } } // 위 코드를 사용하고 싶으면 이렇게 해야한다. function hello(age: number | undefined, name

리터럴, 유니온 / 교차 타입 [내부링크]

리터럴 // 문자열 리터럴 타입 : 정해진 string 값을 가진 것 const userName1 = "Bob"; let userName2: string | number = "Tom"; // Job 타입을 정의한 뒤 interface에서 타입으로 사용하면 무조건 Job 타입에 있는 것만 // 오류가 발생하지 않는다. type Job = "police" | "developer" | "teacher"; interface User { name: string; job: Job; } const user:User = { name: "Bob", job: "police" // 오류x job: "student" // 오류o } 유니온 타입 OR의 의미 동일한 속성의 type을 다르게해서 구별할 수 있는 것을 식별 가능한 유니온 타입이라 한다. interface Car { name: 'car'; color: string; start(): void; } interface Mobile { name: "m

클래스 [내부링크]

class Car { // 타입스크립트에서 class를 작성할 때 멤버 변수는 미리 선언해야한다. color:string; constructor(color: string) { this.color = color; } start() { console.log("start"); } } const bmw = new Car("red"); 맴버 변수를 미리 선언하지 않는 방법 접근 제한자나 readonly 키워드를 활용하면 된다. // public class Car { constructor(public color: string) { this.color = color; } start() { console.log("start"); } } const bmw = new Car("red"); // readonly class Car { constructor(readonly color: string) { this.color = color; } start() { console.log("start"); } }

JS 알고리즘 19일차 - 이진 힙 [내부링크]

정의 힙은 트리 구조의 일종이다. 이진 탐색 트리와도 매우 비슷하다. 이진 탐색 트리와는 다르게 왼쪽과 오른쪽에는 순서가 존재하지 않는다. 최대 이진 힙에서는 부모 노드가 항상 자식 노드보다 큰 값을 가진다. 다시 말해 최대 이진 힙에서는 모든 자식 노드가 부모보다 작다. 그렇지만 형제 노드 사이에는 순서가 보장되지 않는다. 각 노드는 언제나 최대 2개의 자식을 가진다. 항상 왼쪽이 먼저 채워지고 오른쪽이 채워진다. 이진 힙은 언제나 최적의 용량을 가진다. 우선순위 큐에 사용된다. 힙 정렬 배열 안에 있는 모든 인덱스에 대해, 왼쪽 자식은 2n+1에 저장되어 있고, 오른쪽 자식은 2n+2에 저장되어 있다. 반대로 자식의 인덱스에서 (인덱스 - 1) / 2의 소수점을 버린 정수가 부모 인덱스가 된다. Insert 메소드 - 최대 이진 힙 의사코드 값을 하나 입력한다. 배열의 끝에 값을 추가한다. 알맞은 자리로 갈 때까지 버블 업을 해준다. 부모의 자리를 찾는다. ((인덱스 - 1) /

JS 알고리즘 20일차 - 이진 힙(2) [내부링크]

ExtractMax 메소드 소개 힙에서 루트를 제거하는 과정, 즉 최대 힙에서는 최대값을 최소 힙에서는 최소값을 제거한 다음에 프로퍼티를 정리한다. 이 과정을 다운힙 혹은 버블 다운, 퍼콜레이트 다운, 시프트 다운, 트리클 다운, 히피파이 다운, 카스케이드 다운, 최대/최소값 추출 등으로 불린다. 의사코드 최대 이진 힙 클래스에 인수는 받지 않고 이진 힙의 루트를 출력하는 메소드를 작성한다. 루트를 힙에서 삭제한 뒤 루트를 가장 마지막 값으로 변경한다. 해당 인덱스의 왼쪽과 오른쪽 자식을 확인한다. 왼쪽 자식은 2*인덱스+1에 위치한다. 오른쪽 자식은 2*인덱스+2에 위치한다. 자식 중 현재 루트보다 큰 값이 있으면 자리를 변경한다. 이 과정을 자식이 현재 루트보다 작을 때까지 반복한다. 코드 class MaxBinaryHeap { constructor() { this.values = []; } extractMax() { const max = this.values[0]; const

JS 알고리즘 17일차 - Queue(큐) [내부링크]

개념 선입선출로 데이터를 추가하고 제거하는 자료구조 쉽게 말해 줄을 서는 것이다. 먼저 줄을 선 사람이 먼저 입장하는 것과 같은 원리이다. 구현 - 배열 성능을 신경써야 하는 경우라면 직접 큐 클래스를 만드는 것이 좋다. // push, shift를 사용하는 방법 const queue = []; queue.push("FIRST"); queue.push("SECOND"); queue.push("THIRD"); queue.shift(); queue.shift(); queue.shift(); //unshift, pop을 사용하는 방법 queue.unshift("FIRST"); queue.unshift("SECOND"); queue.unshift("THIRD"); queue.pop(); queue.pop(); queue.pop(); 구현 - 단일 연결 리스트 Enqueue 의사코드 값을 하나 입력할 수 있는 함수를 만든다. 입력된 값을 가지고 노드를 새로 만든다. 만약 큐 안에 노드가 없다

JS 알고리즘 17일차 - 이진 탐색 트리 [내부링크]

이진 검색 트리 용어 루트 : 트리 꼭대기에 있는 노드 자식 : 루트에서 멀어지는 방향으로 연결된 노드 부모 : 자식의 반대 개념 형제 : 같은 부모를 가지는 노드 리프 : 자식이 없는 노드 간선 : 한 노드에서 다른 노드로 향하는 화살표 즉, 연결을 의미하는 용어 이진 탐색 트리 특징 이진 트리의 특별한 종류 순서가 있는 정렬 데이터를 가지고 탐색 작업을 한다. 모든 부모 노드는 최대 2개의 자식을 가진다. 부모 노드의 왼쪽에 있는 모든 노드는 언제나 부모보다 작고 오른쪽에 있는 모든 노드는 언제나 부모보다 크다. 즉, 데이터가 특정한 순서로 저장되어 있다. 무언가를 찾아보는 것을 아주 빠르고 쉽게 만들어준다. 무언가를 추가하는 것과 노드의 자리를 찾는 것도 쉽게 해준다. 기본구조 class Node { constructor(value) { this.value = value; this.right = null; this.left = null; } } class BinarySearch

JS 알고리즘 18일차 - 트리 순회(BFS) [내부링크]

넓이 우선 탐색(BFS) 의사코드 Queue를 만들고 방문한 노드를 넣는다. root를 queue에 있는 노드로 변경한다. 현재 root에서 left, right를 확인한 뒤 queue에 넣는다. queue의 값을 제거하고 결과 배열에 넣은 뒤 다음 queue의 노드를 기준으로 반복한다. queue가 비었다면 종료한다. 코드 class Node { constructor(value) { this.value = value; this.right = null; this.left = null; } } class BinarySearchTree { constructor() { this.root = null; } BFS() { const data = [], queue = []; let node = this.root; queue.push(node); while (queue.length) { node = queue.shift() data.push(node.value); if (node.left) qu

JS 알고리즘 18일차 - 트리 순회(DFS) [내부링크]

깊이 우선 탐색(DFS) - 전위 순회 의사코드 방문했던 노드를 저장하는 변수를 만든다. 현재 root를 저장하는 변수를 하나 만든다. 헬퍼 함수를 만든다. 노드의 값을 변수에 넣어서 저장하는 역할을 한다. left가 있으면 재귀 방식으로 헬퍼 함수를 다시 호출한다. right가 있으면 재귀 방식으로 헬퍼 함수를 다시 호출한다. 기본적으로 이 헬퍼 함수는 주어진 노드에 대해 호출된다. 코드 class Node { constructor(value) { this.value = value; this.right = null; this.left = null; } } class BinarySearchTree { constructor() { this.root = null; } DFSPreOrder() { const data = []; let current = this.root; function traverse(node) { data.push(node.value); if (node.left) tr

Doker에서 geth 시작하기(6) [내부링크]

단계 34 : 트랜잭션 전송 node1을 실행할 때 --allow-insecure-unlock을 붙여서 실행한다. 단계 34 : 트랜잭션 전송(2) 전송할 계좌를 unlock한다 Passphrase에는 계좌를 만들 때 입력한 비밀번호를 입력한다. 비밀번호가 일치하면 true가 나온다. 단계 34 : 트랜잭션 전송(3) 5번 인덱스 계좌에서 6번 인덱스 계좌로 트랜잭션을 전송한다. 단계 34 : 트랜잭션 전송(3-1) 트랜잭션 전송이 성공하면 node1에 전송했다는 메시지가 뜬다. 바로 4단계로 넘어가도 괜찮다. 단계 34 : 트랜잭션 전송(3-1-1) 아직 블럭에 담기지 못한 Tx은 각 노드 Local의 Transaction pool에 저장됩니다. (Txpool 상태확인) 단계 34 : 트랜잭션 전송(3-1-2) 3-2) Txpool 상세내역 확인 단계 34 : 트랜잭션 전송(3-1-3) 3-3) 송금한 금액과 수수료 확인 단계 34 : 트랜잭션 전송(4) 트랜잭션을 보냈어도 해당

JS 알고리즘 16일차 - Stack(스택) [내부링크]

스택 개념 후입선출 원칙을 따르는 데이터들의 모음이다. 즉, 가장 마지막으로 추가된 요소가 가장 먼저 제거된다. 구현 - 배열 unshift는 효율적인 방법은 아니다. // push, pop 활용 const stack = []; stack.push(1); stack.pop(); // shift, unshift 활용 stack.unshift(1); stack.shift(); 구현 - 단일 연결 리스트 단일 연결 리스트에서 shift, unshift가 stack에서 push, pop역할을 한다. 왜냐하면 실제 단일 연결 리스트의 pop은 상수 시간을 가지지 못하기 때문이다. class Node { constructor(value) { this.val = value; this.next = null; } } class Stack { constructor() { this.first = null; this.last = null; this.size = 0; } push(value) { const

Doker에서 geth 시작하기(1) [내부링크]

단계 1 : 도커를 설치한다. Docker: Accelerated, Containerized Application Development Docker is a platform designed to help developers build, share, and run modern applications. We handle the tedious setup, so you can focus on the code. www.docker.com 단계 2 : Windows PowerShell에서 도커가 설치되었는지 확인한다. 단계 3 : 도커에서 우분투를 찾는다. 단계 4 : 도커에 우분투를 내려받는다. 단계 5 : 도커 이미지를 확인한다. 단계 6 : 도커 이미지를 container 파일로 생성한다. 다음 포스팅에서 계속

Doker에서 geth 시작하기(2) [내부링크]

단계 7 : 도커를 확인한다. 단계 8 : 도커 우분투 container을 시작한다. 단계 9 : 도커 우분투에 접속한다. 단계 10 : 도커 우분투를 UPDATE한다. 단계 11 : 도커 우분투를 UPGRADE 한다. 단계 12 : 도커 우분투 ip 확인을 위한 net-tools 설치 단계 13 : 도커 우분투 ip를 확인한다. 다음 포스팅에서 계속..

Doker에서 geth 시작하기(3) [내부링크]

단계 14 : geth 설치하기(1) 단계 15 : geth 설치하기(2) 단계 16 : geth 설치하기(3) 단계 17 : geth 설치하기(4) 단계 17 : genesis 생성(1) - 빈 폴더 생성 단계 18 : genesis 생성(2) - vim 설치 단계 19 : genesis 생성(3) - 생성한 폴더로 이동 후 genesis.json 파일 생성 단계 20 : genesis 생성(4) - genesis.json 파일 수정 vim genesis.json으로 파일에 접근 i를 누르면 insert 할 수 있다. 만약 붙여넣기를 하고싶으면 마우스 우클릭을 한다. 작성이 완료되면 esc를 누른 뒤 :wq를 입력하고 나온다. 파일 삭제 시 rm 파일명 혹은 rm -rf 파일명을 한다. genesis.json 파일이 존재한다고 뜨면 ls -a로 전체 파일을 확인한 뒤 genesis.json이 들어간 파일(genesis.json.xxx)을 삭제한 뒤 다시 생성한다. 다음 포스팅에서

Doker에서 geth 시작하기(4) [내부링크]

단계 21 : 노드 생성 node1을 생성한다. 단계 22 : 시작 노드 지정 node1을 지정한다. 단계 23 : geth 시작 네트워크 id는 genesis 파일의 chainId와 동일하다. 단계 24 : 외부에서 노드에 접속하기(1) 단계 25 : 외부에서 노드에 접속하기(2) powershell 창을 하나 더 연다. 도커에 새로운 ubuntu container을 만는다. 새로 만들어진 container에 접속한다. geth를 설치한 뒤 아래 명령어로 접속한다. 예시에서 ip는 node1을 실행시킨 ubuntu의 ip이다. ifconfig를 통해 알아낼 수 있다. 다음 포스팅에서 계속..

Doker에서 geth 시작하기(5) [내부링크]

단계 26 : 신규 계좌 생성 단계 27 : 생성한 계좌 확인 단계 28 : 계좌의 Balance 확인 단계 29 : 생성한 계좌로 mining 시작 단계 30 : 다시 Balance 확인하기 단계 31 : 노드끼리 연결 (1) 새로운 docker container을 만들고 genesis.json과 노드를 만든 뒤 아래의 코드를 실행하다. 단계 31 : 노드끼리 연결 (2) 다른 container에서도 똑같은 과정을 진행한다. 필자는 node1과 node3에서 진행했다. 위에서 새로 만든 노드가 node3이다. 단계 31 : 노드끼리 연결 (3) 필자는 node1 컨테이너에서 해당 코드를 실행했다. 단계 32 : 노드 연결 확인 해당 코드를 node1 컨테이너에서 실행한다. 단계 32 : 노드 연결 확인(2) 해당 코드를 node1 컨테이너에서 실행한다. 단계 33 : static-nodes.json 노드를 실행시킬 때 마다 코드를 작성하지 않아도 연결이 된다. node1 컨테이너에

JS 알고리즘 15일차 - 이중 연결 리스트(get, set) [내부링크]

Get 소개 입력된 인덱스 위치에 있는 노드를 출력한다. 의사코드 인덱스가 유효한지 확인한다. 인덱스가 유효하면 인덱스가 리스트 길이의 절반보다 작거나 같은지 확인한다. 반보다 작거나 같으면 처음부터 시작하고 크면 뒤에서부터 시작한다. 코드 class Node { constructor(val) { this.val = val; this.next = null; this.prev = null; } } class DoublyLinkedList { constructor() { this.head = null; this.tail = null; this.length = 0; } get(index) { let current = null; if (index < 0 || index >= this.length) return false; if (index <= this.length / 2) { current = this.head; let count = 0; while (count !== index) { c

JS 알고리즘 15일차 - 이중 연결 리스트(insert, remove) [내부링크]

Insert 소개 인덱스와 값을 받아 해당 인덱스에 노드를 추가한다. 의사코드 인덱스가 유효한지 확인한다. 인덱스가 0이면 unshift, 인덱스가 this.length면 push를 사용한다. 그렇지 않다면 get을 사용해서 우리가 삽입하려고 하는 값을 바로 전에 값 next로 지정한다. 그리고 next와 prev를 사용해 노드를 연결한다. 마지막으로 길이를 1 증가시키고 true를 출력한다. 코드 class Node { constructor(val) { this.val = val; this.next = null; this.prev = null; } } class DoublyLinkedList { constructor() { this.head = null; this.tail = null; this.length = 0; } get(index) { let current = null; if (index < 0 || index >= this.length) return false; if (i

0.2 제어문(조건문, 반복문) [내부링크]

0.2.1 조건문 조건에는 참 / 거짓에 대한 조건식. if else를 활용. 제어문은 위에서부터 한 개씩 검사를 진행한다. 복수 조건문 복수 조건식을 활용할 경우 elif를 활용하여 표현한다. 중첩 조건문 조건문 속의 조건문을 의미한다. 조건 표현식 조건에 따라 값을 정할 때 활용한다. 삼 항 연산자로 부르기도 한다. True인 경우 값 if 조건 else false인 경우 값 0.2.2 반복문 특정 조건을 만족할 때까지 같은 동작을 계속 반복하고 싶을 때 사용. 반복 문의 종류 while 문 while 조건: 조건식이 참인 경우 반복적으로 코드를 실행 코드 블록이 모두 실행되고, 다시 조건식을 검사하며 반복적으로 실행된다. while 문은 무한 루프를 하지 않도록 종료 조건이 반드시 필요하다. for 문 시퀀스(string, tuple, list, range)를 포함한 순회 가능한 객체(iterable)의 요소를 모두 순회 처음부터 끝까지 모두 순회하므로 별도의 종료 조건이 필요

0.3 함수 [내부링크]

0.3.1 함수 분해(Decomposition) : 기능을 분해하고 재사용 가능하게 만듦. 추상화(Abstraction) : 복잡한 내용을 모르더라도 사용할 수 있도록 재사용과 가독성, 생산성 함수 : 특정한 기능을 하는 코드의 조각, 특정 코드를 매번 다시 작성하지 않고 필요시에만 호출 함수의 종류 내장 함수 : 파이썬에서 기본적으로 포함된 함수 (파이썬 개발자) 외장 함수 : import 문을 통해 사용하며, 외부 라이브러리에서 제공하는 함수 (다른 개발자) 사용자 정의 함수 : 직접 사용자가 만드는 함수 함수의 기본 구조 def func_name (parameters): Docstring function body return returning_value 함수의 선언과 호출 (define & call) def foo(): # foo() return True def add(x,y): # add(2, 3) return x + y 생성 호출 입력 parameter : 함수를 정의할 때

신고 접수 받기 [내부링크]

def solution(id_list, report, k): answer = [] answer_first = [] answer_third = [] report = list(set(report)) for i in id_list: for j in range(len(report)): if i in report[j][:len(i)]: answer_first.append(report[j][len(i)+1:]) for h in id_list: if answer_first.count(h) >= k: for y in range(len(report)): if h in report[y][-len(h):]: answer_third.append(report[y][:-len(h)-1]) for n in id_list: answer.append(answer_third.count(n)) return answer 성공률 70%를 달성했다. for문이 너무 많은 것 같아 조금 수정해야겠다.

0.3 데이터 구조 [내부링크]

0.3.1 데이터 구조 데이터 구조를 활용하기 위해서는 method를 활용 method는 클래스 내부에 정의한 함수, 사실상 함수와 동일 쉽게 설명하자면 객체의 기능이다. 데이터구조. method()의 형태를 띤다 ex) lise.append(10) string.split() 파이썬 공식 문서의 표기법 컴퓨터 언어에서 언어의 문법을 수학적인 수식으로 나타낼 때 사용하는 언어 도구이다. 프로그래밍 언어의 구문을 기술하는데 매우 자연스러운 표기법이다. ex) str.replace(old,new[,count]) old, new는 필수 / [,count]는 선택적 인자를 의미 0.3.2 순서가 있는 데이터 구조 문자열 문자들의 나열 (모든 문자는 str 타입, 변경 불가능한 immutable) 기존의 문자열을 변경하는 게 아니라, 변경된 문자열을 새롭게 만들어서 반환 word = 'apple' print(word) word = 'test' print(word) #문자열의 변경이 아니라 주소

0.4 객체 지향 프로그래밍(oop) [내부링크]

0.4.1 oop 객체 지향 프로그래밍( Object-Oriented Programming) 은 컴퓨터 프로그래밍의 패러다임 중 하나이다. 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 객체들의 모임으로 파악하고자 하는 것, 각각의 객체는 메시지를 주고받고 데이터를 처리할 수 있다. 객체 지향 프로그램 : 프로그램을 여러 개의 독립된 객체들과 그 객체 간의 상호 작용으로 파악하는 프로그래밍 방법 절차 지향 프로그램 : 절차에 따라서 진행하는 프로그램 데이터와 기능(method) 분리, 추상화된 구조 (인터페이스) 객체 지향 프로그래밍이 필요한 이유 추상화 장 / 단점 장점) 클래스 단위로 모듈화 시켜 개발할 수 있으므로 많은 인원이 참여하는 대규모 소프트웨어 개발에 적합 필요한 부분만 수정하기 쉽기 때문에 프로그램의 유지 보수가 쉽다. 단점) 설계 시 많은 노력과 시간이 필요하다. 실행 속도가 상대적으로 느리다. 객체 객체 또는 오브젝트(obj

0.4 객체 지향 프로그래밍 [내부링크]

0.4.1 OOP 메서드 메서드 : 특정 데이터 타입/ 클래스의 객체에 공통적으로 적용 가능한 행위(함수) class Person: def talk(self): print('안녕') def eat(self, food): print(f'{food}를 냠냠') person1 = Person() #init을 불러오는 것 person1.talk() #안녕 person1.eat('피자') #피자를 냠냠 인스턴스 메서드 : 인스턴스(변수)를 처리 인스턴스 변수를 사용하거나, 인스턴스 변수에 값을 설정하는 메서드 호출 시, 첫 번째 인자로 인스턴스 자기 자신(self)이 전달됨 class Myclass: def instance_method(self, arg1, ...): #self가 있으면 인스턴스 메서드다. my_instance = MyClass() my_instance.instance_method() self 인스턴스 자기 자신 매개변수 이름으로 self를 첫 번째 인자로 정의 생성자(con

0.1 Web [내부링크]

Web DAY 1 Web 0.1.1 Web의 정의 웹 사이트의 구성 요소 웹 사이트란 브라우저를 통해 접속하는 웹 페이지들의 모음을 의미한다. 웹 페이지는 글, 그림, 동영상 등 여러가지 정보를 담고 있고 클릭하여 다른 웹 페이지로 이동하는 링크들이 있다. 이러한 링크를 통해 여러 웹 페이지를 연결하는 것을 웹 사이트라고 한다. 구성 요소 HTML 로 웹 사이트의 구조를 만든다. CSS 로 HTML 로 만든 구조를 표현한다. Javascript 를 활용해 동작을 처리한다. 브라우저 웹 사이트는 브라우저를 통해 동작한다. 브라우저 마다 동작이 조금씩 달라서 문제가 생기는 경우가 있고 이것을 파편화라고 한다. 이러한 문제점의 해결책으로 웹 표준이 등장하였다. 웹 표준 웹에서 표준적으로 사용되는 기술이나 규칙을 의미한다. 어떤 브라우저를 사용하든 웹 페이지가 동일하게 보이도록 하는 것이다. (크로스 브라우징)

0.2 HTML [내부링크]

Web day 2 HTML HTML의 의미 웹 페이지를 작성하기 위한 언어이다. 기본 구조 html : 문서의 최상위(root) 요소 head : 문서 메타 데이터 요소 문서 제목, 인코딩, 스타일, 외부 파일 로딩 등등 일반적으로 브라우저에 나타나지 않는 내용 <title> : 브라우저 상단 타이틀 <meta> : 문서 레벨 메타 데이터 요소 <link> : 외부 리소스 연결 요소 (CSS파일, favicon 등) <script> : 스크립트 요소 (javaScript 파일/코드) <style> : CSS 직접 작성 <!DOCTYPE html> #html <html lang="en"> #언어 : 영어 <head> #head <title>HTML 교육</title> <meta charset='UTF-8'> #유니코드를 위한 인코딩 방식 <link href='style.css' rel='stylesheet'> <script src='javascript.js'></script> <sty

0.3 CSS [내부링크]

Web DAY 3 CSS 0.3.1 CSS란 Cascading Style Sheets의 약자 스타일을 지정하기 위한 언어이다. h1 { #h1태그는 선택자(selector) color: blue; #선언(Declaration) font-size: 15px; #font-size(속성,Property), 15px(값,Value) } CSS 구문은 선택자를 통해 스타일을 지정할 HTML 요소를 선택한다. 중괄호 안에서는 속성과 값, 하나의 쌍으로 이뤄진 선언을 진행한다. 각 쌍은 요소의 속성, 부여할 값을 의미한다. 속성 : 어떤 스타일 기능을 변경할 지 결정 값 : 어떻게 스타일 기능을 변경할지 결정 0.3.2 정의 방법 인라인 (inline) 인라인을 사용하면 실수가 잦아진다. 내부 참조 내부 참조를 사용하면 코드의 길이가 길어진다. 외부 참조 가장 많이 사용하는 방식으로 분리된 CSS파일을 참조하여 사용한다. 0.3.3 CSS 선택자 기본 선택자 전체 선택자 (*), 요소 선택자 클

단계별로 풀어보기-python (1 단계) [내부링크]

1000번 간단한 합을 구하는 문제이다. map을 이용해 A와 B를 int로 입력받아서 합을 출력한다. A,B = map(int,input().split()) print(A+B) 1001 간단한 차를 구하는 문제이다. A,B = map(int,input().split()) print(A-B) 1008번 간단한 나눗셈을 구하는 문제이다. A,B = map(int,input().split()) print(A/B) 2588 곱셈의 과정을 출력하는 문제이다. 문자열로 입력을 받아 일의 자리부터 하나씩 곱셈을 시작하고 마지막에 두 수의 곱을 출력한다. A = input() B = input() print(int(A) * int(B[2])) print(int(A) * int(B[1])) print(int(A) * int(B[0])) print(int(A)*int(B)) 10171번 주어진 모양을 나타내는 문제이다. escape sequence를 활용하여 나타내면 된다. print('\\ /\\

단계별로 풀어보기-python (1단계) [내부링크]

10430번 두 수의 사칙 연산의 순서를 확인하는 문제이다. A, B, C = map(int,input().split()) print((A+B)%C) print(((A%C) + (B%C))%C) print((A*B)%C) print(((A%C) * (B%C))%C) 10869번 간단한 사칙 연산을 구하는 문제이다. A,B = map(int,input().split()) print(A+B) print(A-B) print(A*B) print(A//B) print(A%B) 10926번 f-string을 사용하는 문제이다. char = input() print(f'{char}??!') 10998번 간단한 곱을 구하는 문제이다. A,B = map(int,input().split()) print(A*B) 18108번 불기를 구하는 문제이다. year = int(input()) print(year - 543) 25083번 모양을 나타내는 문제이다. escape sequence를 이용하면 된다.

단계별로 풀어보기 - python (2 단계) [내부링크]

1330번 A, B = map(int,input().split()) # 두 수를 입력 받음 if A > B: # 두 수의 크기를 비교 print('>') elif A < B: print('<') else: print('==') 2480번 A, B, C = map(int,input().split()) # 세가지 수를 입력 받는다. num_list = [A, B, C] # 세 가지 수를 리스트로 만듦 sum = 0 # 합을 초기화 for i in num_list: if num_list.count(i) == 3: # 리스트 내에 같은 원소가 3개인 경우 sum = 10000 + i*1000 # sum을 출력하고 나온다. break elif num_list.count(i) == 2: # 리스트 내에 같은 원소가 2개인 경우 sum = 1000 + i * 100 # sum을 출력하고 나온다. break elif num_list.count(i) == 1: # 위의 2 경우가 아닌 경우 sum을

일주일 고생한 나를 위한 휴식 [내부링크]

2022년 8월 06일 매일 4시간 씩 잠을 잔 탓에 피로가 누적되었다. 꿀같은 휴일이라 알람 소리에 방해를 받지 않고 일어났다. AM 11:30 늦게 일어난 나를 위해 여자친구가 점심으로 타코야끼를 시켜줬다. 너무 고마웠고 무엇보다 치즈 타코야끼가 맛있어서 행복한 점심이였다. 점심을 먹고 여유롭게 할 일을 하다 잠깐 쉬고싶어 3시쯤 쇼파에 누웠다. 아침에 잠이 부족했는지 다시 기절하듯 잠에 들었고 일어나보니 7시가 넘었다. PM 7:30 일어나서 저녁으로 불고기를 해 먹었다. 오늘은 잠과 식사가 전부인 하루였다. 하지만 평일에 고생한 나에게 주는 오프 데이이니깐 알찬 하루란 생각이 들었다.

0.4 반응형 웹 [내부링크]

Web DAY 4 CSS Layout / bootstrap Float 박스를 왼쪽, 오른쪽으로 이동시켜 텍스트를 포함한 인라인 요소들이 주변을 감싸도록한다. 요소가 Normal flow를 벗어나도록 함. 속성 none : 기본 값 left : 요소를 왼쪽으로 띄운다. right : 요소를 오른쪽으로 띄운다. Flexbox 행과 열 형태로 아이템들을 배치하는 1차원 레이아웃 모델 블록 요소를 인라인 요소로 만든다. 축 main axis (메인 축) cross axis (교차 축 , 메인 축과 수직) 구성 요소 Flex container (부모 요소) : flex를 적용시킬 때 부모 요소에 적용. Flex item (자식 요소) inline-flex : 테두리가 요소만큼 줄어든다. Flexbox 축 flex-direction : row (기본 값, x 축) flex-direction : row-reverse (-x 축) flex-direction : column (-y 축) flex-d

단계별로 풀어보기 - python (3 단계) [내부링크]

1110번 # 수가 10보다 작다면 앞에 0을 붙여 두 자리로 만들고 각 자리를 더함 # 수의 가장 오른쪽 수와 구한 합의 가장 오른쪽 자리를 이어 붙여 새로운 수를 만듬 import sys N = sys.stdin.readline() # 첫 번째 숫자를 입력 받음 num = N[:] # 얕은 복사로 같은 수를 다른 주소로 복사 sum = 0 # N의 두 수를 더하는 함수 cnt = 1 # 카운터 하는 변수 if 0 <= int(N) < 10: # N이 10 미만의 경우 N = str(0)+N while True: sum = int(N[0])+int(N[1]) # sum을 구함 if int(str(int(N)%10)+str(sum%10)) == int(num): #sum이 첫 수와 같음 나옴 break else: N = str(int(N)%10) + str(sum%10) #아니면 N을 교체함 cnt += 1 # 카운터를 1 증가 print(cnt) 2438번 import sys N

단계별로 풀어보기 - python ( 3 단계) [내부링크]

8393번 import sys n = int(sys.stdin.readline()) # 입력을 받는다. sum = 0 # 합을 초기화 한 함수. for i in range(1,n+1): sum += i # n번 동안 for문이 실행되고 합을 누적한다. print(sum) 10871번 import sys N, X = map(int,sys.stdin.readline().split()) # 정수 N과 정수X를 입력받음 A = sys.stdin.readline().rstrip('\n').split(' ') #문자열로 받은 lst = str() # 빈 문자열을 #수열을 띄어쓰기를 기준으로 나눠 리스트로 만듬 for i in A: if int(i) < X: # 수를 비교해서 X보다 작으면 lst += i+' ' # 문자열에 추가 else: continue print(lst) 10950번 import sys T = int(sys.stdin.readline().rstrip('\n')) # 줄 갯수

단계별로 풀어보기 - python ( 3 단계) [내부링크]

11022번 import sys T = int(sys.stdin.readline()) # 테스트 갯수를 입력함 for i in range(1,T+1): # 테스트 갯수만큼 수를 입력 받고 합을 출력 A, B = map(int,sys.stdin.readline().split()) print(f'Case #{i}: {A} + {B} = {A+B}') 15552번 import sys T = int(sys.stdin.readline()) # 입력을 input 보다 더 빨리 받는다. for i in range(1,T+1): A, B = map(int,sys.stdin.readline().split()) # 여러 개의 입력을 받을 때 print(A+B) 25304번 import sys X = int(sys.stdin.readline()) # 총 금액 N = int(sys.stdin.readline()) # 물건 갯수 sum = 0 for i in range(1,N+1): # 물건 수 만큼 반복

단계별로 풀어보기 - python ( 4 단계) [내부링크]

1546번 # 자기 점수 중 최댓값을 M # 모든 점수를 점수/M*100 # 과목의 갯수 N개 import sys N = int(sys.stdin.readline()) # 과목 수를 입력 받음 lst = list(map(int,sys.stdin.readline().rstrip('\n').split())) # 과목의 점수를 리스트로 만듬 sum = 0 #합을 0으로 초기화 for i in lst: sum += ((int(i)/int(max(lst)))*100) # 새로운 과목 점수를 계산 print(sum/N) # 새로운 과목 평균을 구함 2562번 import sys N = [] for i in range(1,10): # 9개의 숫자를 받기 위한 반복문 num = int(sys.stdin.readline().rstrip('\n')) N.append(num) # 빈 리스트에 저장 print(max(N)) # 최댓값을 구함 print(N.index(max(N))+1) # 최댓값의 인덱스

단계별로 풀어보기 - python ( 5 단계) [내부링크]

1065번 # 어떤 양의 정수 X의 각 자리가 등차수열 그 수를 한수 # 등차수열은 연속된 두 개의 수의 차이가 일정 # N에서 한수 개수를 출력 N = int(input()) # 입력은 받음 def hansu(Num): # 한수의 갯수를 출력하는 함수 result = 0 # 출력 cnt = 0 # 갯수를 새는 변수 if Num < 100: # 100 미만의 수는 자기 자신이 한수의 갯수 result = Num + cnt else: for i in range(100,Num+1): # 100 이상의 수는 각 자리의 차가 같으면 cnt를 증가 if int(str(i)[1]) - int(str(i)[0]) == int(str(i)[2])-int(str(i)[1]): cnt += 1 result = cnt + 99 # 100보다 큰 수는 cnt에 99를 더해 결과를 출력 return result print(hansu(N)) 4673번 # d(n) = n과 n의 각 자리수를 더하는 함수 #

0.1 정렬 [내부링크]

algorithm day1 정렬 0.1.1 버블 정렬 (Bubble Sort) 인접한 두 개의 원소를 비교하여 자리를 계속 교환하는 방식 과정 첫 번째 원소부터 인접한 원소끼리 계속 자리를 교환하면서 마지막 자리까지 이동 한 단계가 끝나면 가장 큰 원소가 마지막 자리로 정렬 시간 복잡도 O(n**2) def BubbleSort(a, N): # 정렬한 List, N 원소 수 for i in range(N-1, 0, -1): # 범위의 끝 위치 for j in range(0,i): if a[j] > a[j+1]: a[j], a[j+1] = a[j+1], a[j] 0.1.2 카운팅 정렬 (Counting Sort) 항목들의 순서를 결정하기 위해 집합에 각 항목이 몇 개씩 있는지 세는 작업을 하여, 선형 시간에 정렬하는 효율적인 알고리즘 정수나 정수로 표현할 수 있는 자료에 대해서만 적용 가능 카운트들을 위한 충분한 공간을 할당하려면 집합 내의 가장 큰 정수를 알아야 한다. 시간 복잡도 O

0.1 배열 [내부링크]

algorithm day2 배열 0.1.1 2 차원 배열 1 차원 list를 묶어놓은 list 2 차원 이상의 다 차원 list는 차원에 따라 index를 선언 2 차원 list의 선언 : 세로 길이 ( 행의 개수 ), 가로 길이 ( 열의 개수 )를 필요로 한다. python에서는 데이터 초기화를 통해 변수 선언과 초기화가 가능하다. # 행 우선 순회, i 행 j 열 for i in range(n): for j in range(m): Array[i][j] #필요한 연산 수행 # 열 우선 순회, i 행 j 열 for j in range(m): for i in range(n): Array[i][j] # 필요한 연산 수행 # 지그재그 순회, i 행 j 열 for i in range(n): for j in range(m): Array[i][j+(m-1-2*j)*(i%2)] # 필요한 연산 수행 델타를 이용한 2 차 배열 탐색 # 2차 배열의 한 좌표에서 4방향의 인접 배열 요소를 탐색 #

변덕스러운 날씨에 기분 좋은 선물! [내부링크]

2022년 8월 13일 요즘 비가 너무 많이 와서 기분이 별로였다. 화창하다가 어느 순간에 폭우가 쏟아지고 비로 인해 날씨도 너무 습해서 에어컨이 없이는 너무 힘든 여름이다. 이런 나를 위해 여자친구가 특별한 선물을 해주었다. 평소에 쓰던 컵이 이상해 보였는지 아주 화려한 녀석을 보내주었다. 평소 술을 즐기지는 않지만 이 녀석으로 물을 마시기는 아까우니 맥주라도 마셔야겠다 ㅎㅎ

단계별로 풀어보기 - python ( 6 단계) [내부링크]

1152번 # 영어 대소문자와 공백으로 이루어진 문자열이 주어짐 # 단어의 갯수를 출력 # 첫 줄에 문자열이 주어진다. arr = list(map(str,input().split())) print(len(arr)) 1157번 # 알파벳 대소문자로 된 단어에서 가장 많이 사용된 알파벳을 구함 # 첫째 줄에 알파벳 대소문자로 이뤄진 단어가 주어짐 import sys from unittest import result # 단어를 입력 받음 # 단어를 전부 소문자로 바꿈 words = sys.stdin.readline().rstrip('\n').lower() words_dict = {} max_num = 0 # 딕셔너리에 알파벳 키와 갯수 벨류를 받음 for i in words: if words_dict.get(i): words_dict[i] += 1 else: words_dict[i] = 1 # 벨류값이 가장 큰 것을 result에 저장 for i in words_dict: if max_n

단계별로 풀어보기 - python ( 6 단계) [내부링크]

2941번 # 크로아티아 알파벳의 갯수를 찾는다 # 첫줄에 최대 100글자의 단어가 주어진다. arr_dict = {'c=':'č','c-':'ć','dz=':'dž','d-':'đ', 'lj':'lj','nj':'nj','s=':'š','z=':'ž'} arr = input() cnt = 0 # 딕셔너리의 키 값이 문자열에 포함이 되면 for i in arr_dict.keys(): if i in arr: # 같은 크로아티아 알파벳이 존재하면 if arr.count(i) > 1: cnt += arr.count(i) else: cnt += 1 arr = arr.replace(i,',') # 나머지 알파벳의 갯수를 측정 for i in arr: if i == ',': continue else: cnt += 1 print(cnt) 5622번 # 1을 걸려면 총 2초가 필요 # 1보다 큰 수는 1초씩 더 걸림 # 첫 줄에는 알파벳이 대문자로 주어짐 char = input() arr = [[

늦은 여름 나기 [내부링크]

2022년 8월 21일 이번 여름은 물놀이 계획이 없었다. 여자친구 언니 커플이랑 좋은 기회가 생겨서 오늘 첫 계곡을 다녀왔다. 물이 엄청 차가워서 놀랐지만 물에 적응을 하니 더위가 싹 가시는 기분이었다. 이번 물 놀이의 하이라이트는 역시 먹거리!! 형이 맛있는 것을 잔뜩 사와서 너무 맛있게 먹을 수 있었다. 여자친구 덕분에 좋은 사람들과 행복한 시간을 보내고 이번 여름을 잘 마무리해서 좋은 하루였다.

단계별로 풀어보기 - python ( 7 단계) [내부링크]

1193번 import sys # 첫 줄에는 x가 주어진다. N = int(sys.stdin.readline()) n = 1 # j번째까지의 합 i = 1 # j의 인덱스 while n < N: i += 1 n += i n -= i i -= 1 # 사선 위, 사선 아래 di = [-1, 1] dj = [1, -1] if (i+1)%2: x, y = i+1, 1 for i in range(N-n-1): x += di[0] y += dj[0] else: x, y = 1, i + 1 for i in range(N-n-1): x += di[1] y += dj[1] print(f'{x}/{y}') 1712번 # 고정비 A, 가변비B, 가격C # 손익 분기점을 계산 # 첫 줄에 A, B, C가 주어진다. import sys A, B, C = map(int,sys.stdin.readline().rstrip('\n').split()) i = 0 D = C - B # 가변비가 가격보다 높으면 -1을

단계별로 풀어보기 - python ( 7 단계) [내부링크]

2839번 # 설탕 N킬로그램을 배달해야 함 # 3, 5킬로그램 봉지가 있다 # 최소 개수의 봉지를 배달할 수 있다. # 첫째 줄에 N이 주어진다. N = int(input()) # 3~15까지는 규칙이 있다. 따라서 따로 배열을 만들어서 사용할 것이다. arr = [[3,5],[6,8,10],[9,11,13,15],[12,14]] cnt = 0 # 먼저 5의 배수이면 그냥 출력한다. if not N%5: cnt = N%5 while N > 15: N -= 5 cnt += 1 # 5로 계속 빼다가 N이 15보다 작을 때 리스트에 있는 값 중 없으면 -1 있으면 배열에 1을 더해서 결과를 낸다. for i in range(len(arr)): if N in arr[i]: cnt += (i + 1) break else: cnt = -1 print(cnt) 2869번 # 달팽이는 길이가 V인 나무에 올라간다. # 낮에 A정도 올라갈 수 있다. # 밤에 B정도 미끄러진다. # 모두 올라갈려면

0.1 스택 [내부링크]

algorithm day3 스택 0.1.1 스택(Stack) 정의 물건을 쌓아 올리듯 자료를 쌓아 올린 형태의 자료 구조 스택에 저장된 자료는 선형 구조를 갖는다. 선형 구조 : 자료 간의 관계가 1 대 1의 관계를 갖는다. 비선형 구조 : 자료 간의 관계가 1대 N의 관계를 갖는다. (ex. tree) 스택에 자료를 삽입하거나 스택에서 자료를 꺼낼 수 있다. 후입선출 (LIFO : Last-In-First-Out) : 마지막에 삽입한 자료를 가장 먼저 꺼냄. 구현 자료 구조 : 자료를 선형으로 저장할 저장소 배열을 사용할 수 있다. 저장소 자체를 스택이라 부르기도 한다. 스택에서 마지막 삽입된 원소의 위치를 top이라고 부른다. 연산 push(삽입) : 저장소에 자료를 저장 # push 구현 def push(item, size): global top top += 1 if top == size: print('overflow') # 디버깅용 else: stack[top] = item

뭉지와 나들이 [내부링크]

2021년 8월 27일 계획은 다음 주에 만나는 것이었지만 보고싶어 한 걸음에 달려왔다. 고로 오늘은 '어쿠스틱콜라보 - 너무 보고싶어'를 들어야겠다. 오늘 만나자마자 선물로 찌지리 오리 인형을 받았다. 나는 억울하게 생긴 인형이 너무 귀여워서 맘에 쏙 들었다. 찌지리 오리 인형과 뭉지 지난주에 옷을 사주기로 약속해서 서로에게 옷을 선물했다. 내가 사준 셔츠와 갈색 무언가가 너무 귀엽고 잘 어울려서 만족스러웠다. 다음에두 이쁜 옷을 사주고싶다!

0.1 스택-2(stack-2) [내부링크]

algorithm day4 스택 활용 0.1.1 계산기 문자열로 된 계산식이 주어질 때, 스택을 이용하여 이 계산식의 값을 계산할 수 있다. 표기법 중위 표기법 (infix notation) : 연산자를 피연산자의 가운데 표기하는 방법 (ex. A+B) 후위 표기법 (postfix notation) : 연산자를 피연산자 뒤에 표기하는 방법 (ex. AB+) 방법 1 - 중위 표기법의 수식을 후위 표기법으로 변경. (스택 활용) 1. 수식의 각 연산자에 대해서 우선순위에 따라 괄호를 사용하여 다시 표현한다. 2. 각 연산자를 그에 대응하는 오른쪽 괄호의 뒤로 이동시킨다. 3. 괄호를 제거한다 # EX) A*B-C/D # 1. ((A*B)-(C/D)) # 2. ((AB)*(CD)/)- # 3. AB*CD/- 변환 알고리즘 1. 입력받은 중위 표기식에서 토큰 (피연산자, 연산자) 을 읽는다. 2. 토큰이 피연산자이면 토큰을 출력한다. 3. 토큰이 연산자 (괄호 포함) 일 때, 이 토큰이

0.1 큐 (Queue) [내부링크]

algorithm day5 큐 0.1.1 Queue 큐의 특성 스택과 마찬가지로 삽입과 삭제의 위치가 제한적인 자료구조 선입 선출 구조 (FIFO : First in First Out) : 큐에 삽입한 순서대로 원소가 저장, 가장 먼저 삽입된 원소가 가장 먼저 삭제된다. 기본 연산 enQueue(item) : 큐의 뒤쪽 (rear 다음)에 원소를 삽입하는 연산 deQueue() : 큐의 앞쪽(front)에서 원소를 삭제하고 반환하는 연산 createQueue() : 공백 상태의 큐를 생성하는 연산 isEmpty() : 큐가 공백 상태인지를 확인하는 연산 isFull() : 큐가 포화 상태인지를 확인하는 연산 Qpeek() : 큐의 앞쪽(front)에서 원소를 삭제 없이 반환하는 연산 연산 과정 1. 공백 큐 생성 : createQueue() 2. 원소 A 삽입 : enQueue(A) 3. 원소 B 삽입 : enQueue(B) 4. 원소 반환/삭제 : deQueue() - A 삭제 5

0.1 트리(Tree) [내부링크]

algorithm day6 트리 0.1.1 트리 개념 비선형 구조 무향 그래프 (방향이 없는 그래프) 원소들 간에 1:n 관계를 가지는 자료구조 원소들 간에 계층 관계를 가지는 계층형 자료 구조 상위 원소에서 하위 원소로 내려가면서 확장되는 트리 모양의 구조 정의 한 개 이상의 노드로 이루어진 유한 집합, 다음 조건을 만족함 노드 중 최상위 노드를 root or vertex라 한다. 나머지 노드들은 n 개의 분리 집합 T1,... TN으로 분리될 수 있다. T1... TN은 각각 하나의 트리가 되며(재귀적 정의) 루트의 부 트리(subtree)라 한다. 자식을 가지지 않는 노드를 leaf or 단말 노드라고 한다. 용어 노드 (node) - 트리의 원소 간선 (edge) - 노드를 연결하는 선, 부모 노드와 자식 노드를 연결 루트 노드 (root node) - 트리의 시작 노드 형제 노드(sibling node) - 같은 부모 노드의 자식 노드들 조상 노드 - 간선을 따라 루트 노드

0.2 트리 [내부링크]

algorithm day7 트리 0.2.1 수식 트리 정의 수식을 표현하는 이진 트리 연산자는 루트 노드이거나 가지 노드 피연산자는 모두 잎 노드 순회 중위 순회 : A/B*C*D+E (식의 중위 표기법) 후위 순회 : A B / C * D * E (식의 후위 표기법) 전위 순회 : +**/A B C D E (식의 전휘 표기법) 0.2.2 이진 탐색 트리 정의 탐색 작업을 효율적으로 하기 위한 자료 구조 모든 원소는 서로 다른 유일한 키를 갖는다. key(왼쪽 서브 트리) < key(루트 노드) < key(오른쪽 서브 트리) 왼쪽 서브 트리와 오른쪽 서브 트리도 이진 탐색 트리다. 중위 순회하면 오름차순으로 정렬된 값을 얻을 수 있다. 탐색 연산 루트에서 시작 탐색할 키값 x를 루트 노드의 키값과 비교한다. (키값 x = 루트 노드의 키값)인 경우 : 원하는 원소를 찾았으므로 탐색 연산 성공 (키값 x < 루트 노드의 키값)인 경우 : 루트 노드의 왼쪽 서브 트리에 대해서 탐색 연산

0.1 Django [내부링크]

Django day1 Django 0.1.1 background Framework : 서비스 개발에 필요한 기능들을 미리 구현해서 모아 놓은 것 Web Application : 웹에서 데이터를 생성하고 동작을 수행하는 SW Web Application을 미리 만들어 둔 것을 Web Application Framework Web server : 사용자의 요청을 받아서 응답을 실시 Web Application server : WAS, Application + server + container 서버에서 클라이언트에 따라 HTML(data)를 생성해서 응답을 함 클라이언트와 서버 웹은 클라이언트-서버로 이루어져 있음 DNS (Domain Name Service) : ip 주소를 이름으로 변경해 주는 서비스 port 번호 : 컴퓨터끼리 정보를 교환하기 위해 사용하는 가상의 논리적 접속 위치 요청을 보낼 때 ip 주소와 port 번호를 같이 받아야 한다. port 번호를 안 적으면 기본값이 8

0.2 Django [내부링크]

Django day1 Django 0.2.1 Django Template 요청과 응답 URL -> VIEW -> TEMPLATE 순의 작성 render() render(request, template_name, context) # request : 응답을 생성하는 데 사용되는 요청 객체 # template_name : 템플릿의 전체 이름 또는 템플릿 이름의 경로 # context : 템플릿에서 사용할 데이터 (딕셔너리 타입으로 작성) 주어진 템플릿을 주어진 컨텍스트 데이터와 결합하고 렌더링 된 텍스트와 함께 HttpResponse(응답) 객체를 반환하는 함수 Templates 실제 내용을 보여주는데 사용되는 파일 파일의 구조나 레이아웃을 정의 기본 경로 : app 폴더 안에 templates 폴더, app_name/templates/ Django Template '데이터 표현을 제어하는 도구이자 표현에 관련된 로직' HTML 정적 부분과 동적 콘텐츠 삽입 Django Template

결혼식 [내부링크]

2022년 9월 04일 토요일에 뭉지의 친구 결혼식에 방문했다. 아침부터 결혼식 준비를 도와주었다. 처음하는 경험이라 색다르고 재미있었다. 식은 오후 늦게 시작했다. 사전 준비가 너무 많아 복잡해 결혼에 대한 긍정적인 생각이 없었는데 식을 올리는 모습이 너무 예뻐 나도 결혼을 하고 싶은 생각이 많이 들었다. 결혼식을 준비하면서 잠깐 찍은 사진 결혼식이 끝나고 먹은 뷔페

0.1 Model [내부링크]

Django day2 Model 0.1.1 Namespace 개요 URL namespace를 사용하면 서로 다른 앱에서 동일한 URL 이름을 사용하는 경우에는 이름이 지정된 URL을 고유하게 사용할 수 있다. URL 참조 ':' 연산자를 사용하여 지정 ex. app_name이 articles, URL name이 index인 주소 참조 articles : index URL 참조와 template namespace를 같이 해주어야 한다. app_name을 지정한 이후에는 url 태그에서 반드시 app_name : url_name 형태로만 사용해야 한다. 그렇지 않으면 NoReverceMatch 에러가 발생한다. NoReverceMatch가 발생하면 url태그만 확인하면 된다. Template namespace Django는 기본적으로 app_name/templates/경로에 있는 templates 파일들만 찾을 수 있으며, settings.py의 INSTALLED_APPS에 작성한 ap

0.2 Model [내부링크]

Django day2 Model 0.2.1 CRUD Create/Read/Update/Delete 생성/조회/수정/삭제 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능 4가지를 일컫는 말이다. Create 첫번째 방법 article = Article() 클래스를 통한 인스턴스 생성 article.title 클래스 변수명과 같은 이름의 인스턴스 변수를 생성 후 값 할당 article.save() 인스턴스로 save 메서드 호출 두번째 방법 인스턴스 생성 시 초기 값을 함께 작성하여 생성 세번째 방법 create() 메서드 활용 .save() 객체를 데이터베이스에 저장한다. 데이터 생성 시 save를 호출하기 전에는 객체의 id값은 None id 값은 django가 아니라 데이터베이스에서 계산되기 떄문이다. 단순히 모델 클래스를 통해 인스턴스를 생성하는 것은 DB에 영향을 미치지 않기 때문에 반드시 save를 호출해야 테이블에 레코드가 생성된다. READ all() Que

0.1 Form and ModelForm [내부링크]

Django day3 Form and ModelForm 0.1.1 Django form 개요 사용자가 입역한 데이터가 우리가 원하는 데이터 형식이 맞는지에 대한 유효성 검증이 반드시 필요하다. 이러한 유효성 검증은 많은 부가적인 것들을 고려해서 구현해야 하는데, 이는 개발 생산성을 늦추고 쉽지 않은 작업이다. Django Form은 이 과정에서 과중한 작업과 반복 코드를 줄여준다. Form Class Form Class를 선언하는 것은 Model Class를 선언하는 것과 비슷한다. 비슷한 이름의 필드 타입을 많이 가지고 있다. Model과 마찬가지로 상속을 통해 선언한다. Form rendering options <lable> & <input> 쌍에 대한 3가지 출력 옵션 1. as_p() 각 필드가 단락(p 태그)으로 감싸져서 렌더링 2. as_ul() 각 필드가 목록 항목(li 태그)으로 감싸져서 렌더링 ul 태그는 직접 작성해야 한다. 3. as_table() 각 필드가 테이

0.2 Form and ModelForm [내부링크]

Django day3 Form and ModelForm 0.2.1 Handling HTTP requests 개요 HTTP requests 처리에 따른 view 함수 구조 변화 new-create, edit-update의 view 함수 역할의 공통점, 차이점 공통점 new-create는 모두 CREATE 로직을 구현하기 위한 공통 목적 edit-update는 모두 UPDATE 로직을 구현하기 위한 공통 목적 차이점 new와 edit는 GET 요청에 대한 처리만을, create와 update는 POST 요청에 대한 처리만을 진행한다. Create 1. new와 create view 함수를 합친다. 2. 불필요해진 new의 view 함수와 url path를 삭제한다 3. new.html -> create.html로 이름을 변경하고 action 속성 값을 수정한다. 4. 템플릿 경로 수정 5. new 관련 링크 수정 Update 1. edit과 update view 함수를 합친다. 2. 불

0.1 authentication system [내부링크]

Django day 4 authentication system 0.1.1 The Django authentication system 개요 인증 시스템은 인증과 권한 부여를 함께 제공(처리) 필수 구성은 settings.py에 이미 포함되어 있다. (django.contrib.auth) Authentication(인증) 신원 확인 사용자가 자신이 누구인지 확인하는 것 Authorization(권한, 허가) 권한 부여 인증된 사용자가 수행할 수 있는 작업을 결정 사전 설정 두 번째 app accounts 생성 및 등록 url 분리 및 매핑 User 모델 대체하기 AbstractUser를 상속받는 커스텀 User 클래스 작성 Django 프로젝트에서 User를 나타내는데 사용하는 모델을 방금 생성한 커스텀 User 모델로 지정 admin.py에 커스텀 User 모델을 등록 기본 user 모델이 아니기 때문에 등록하지 않으면 admin site에 출력되지 않는다. 0.1.2 HTTP Coo

0.2 Authentication system [내부링크]

Django day4 Authentication system 0.2.1 Authentication with User 개요 템플릿에서 인증 관련 데이터를 출력하는 방법 현재 로그인 되어있는 유저 정보 출력하기 settings.py의 context processors 설정값 때문에 base 템플릿에서 context 데이터 없이 user 변수를 사용할 수 있다. context processors 템플릿이 렌더링 될 때 호출 가능한 컨텍스트 데이터 목록 작성된 컨텍스트 데이터는 기본적으로 템플릿에서 사용 가능한 변수로 포함된다. 회원 가입 회원가입은 User를 Create 하는 것이며 UserCreationForm built-in-form을 사용한다. UserCreationForm 주어진 user name과 password로 권한이 없는 새 user를 생성하는 ModelForm 3개의 필드를 가진다. user name(from the user model) password1 password2

0.3 Authentication system [내부링크]

Django day4 Authentication system 0.3.1 Limiting access to logged-in users 개요 로그인 사용자에 대한 접근 제한하기 is_authenticated User model의 속성 중 하나 사용자가 인증되었는지를 알 수 있는 방법 모든 User 인스턴스에 대해 항상 True인 읽기 전용 속성 AnonymousUser(로그인하지 않은 유저)에 대해서는 항상 False 일반적으로 reuest.user에서 이 속성을 사용한다. (request.user.is_authenticated) 권한과는 관련이 없으며, 사용자가 활성화 상태이거나 유효한 세션을 가지고 있는지도 확인하지 않는다. login_required login_required decorator 사용자가 로그인 되어 있으면 정상적으로 view 함수를 실행 로그인하지 않은 사용자의 경우 settings.py의 LOGIN_URL 문자열 주소로 redirect LOGIN_URL의 기본

노는게 젤 좋아 [내부링크]

2022년 9월 11일 뭉지네 뭉뭉이 쿠키랑 은구비공원에 가서 산책을 했다. 태풍이 지나가고 날이 너무 좋아서 돗자리를 가져가 하루종일 뒹굴거리고 싶었다. 마치 파리의 몽마르뜨언덕 같았달까. 많은 사람들이 쿠키를 귀여워 해줘서 내가 더 뿌듯했다. 그리고 집으로 가서 황치즈쿠키와 블루베리쿠키치즈케이크를 먹었다. 뭉지는 참 '쿠키'를 좋아한다. 맹날 쿠키 종류를 많이 먹는다. 내가 더 사줘야겠다. (맨날 다이어트 한다고 말한다.) 그래도 나는 그런 뭉지가 좋다. 오늘은 별다방에 와서 콩부를 하려고 하는데 뭉지 책이 흉기다!!!! 이제는 뭉지랑 공부를 ㅈㅣ인짜로 해야한다. 안녕 뭉지와 나 쿠키와 뭉지의 두꺼운 책

단계별로 풀어보기 - python ( 8 단계) [내부링크]

1929번 # M이상 N이하의 소수를 모두 출력 import math m,n = map(int,input().split()) l = [True for i in range(n + 1)] # 처음엔 모든 수가 소수(True)인 것으로 초기화 for i in range(2, int(math.sqrt(n)) + 1): # 2부터 n의 제곱근까지 if l[i] == True: # i가 소수인 경우 (남은 수인 경우) # i를 제외한 i의 모든 배수를 지우기 j = 2 while i * j <= n: l[i * j] = False j += 1 # 모든 소수 출력 for i in range(m, n + 1): if l[i]: if i != 1: print(i) 1978번 # 주어진 수 N개 중에서 소수가 몇 개인지 출력 # 소수를 구하는 함수 def sosu(num): cnt = 0 # 소수를 저장하는 변수 for i in num_lst: # 받은 숫자들을 하나씩 검사 result = -1 #

단계별로 풀어보기 - python ( 8 단계) [내부링크]

4948번 # 입력은 여러 개의 테스트 케이스 # 입력의 마지막에는 0 # n이 주어졌을 때, n보다 크고, 2n보다 작거나 같은 소수의 개수를 구함 import math n_lst = [1 for _ in range(2 * 123456+1)] # 입력의 2배 크기의 리스트를 만듬 for i in range(2, int(math.sqrt(123456 * 2)) + 1): if i: # 소수가 아닌 수 start = 2 # 소수의 배수는 걸러낸다. while i * start <= 2 * 123456: n_lst[i * start] = 0 start += 1 while True: n = int(input()) # 입력을 받음 if not n: break if n == 1: print(1) else: print(n_lst[n+1:2*n+1].count(1)) 9020번 # 골드바흐 수 : 2보다 큰 모든 짝수는 두 소수의 합으로 나타낼 수 있고 이때 수를 의미 # 골드바흐 파티션 : 짝

SWEA-Magnetic(1220) [내부링크]

for tc in range(1, 11): N = int(input()) # 1은 N극 성질, 2는 S극 성질 # 위에 N극, 밑에 S극 arr = [list(map(int,input().split())) for _ in range(100)] cnt = 0 for i in range(N): stack = [] for j in range(N): if arr[j][i] == 1 and not stack: stack.append(1) elif stack and arr[j][i] == 2: stack.pop() cnt += 1 print(f'#{tc} {cnt}')

SWEA-간단한 369 게임(1926) [내부링크]

# 입력으로 정수 N이 주어짐 # 박수를 치는 부분에 '-'출력 # 박수를 두번 칠 때는 '--' # 정수 N N = int(input()) for i in range(1, N+1): cnt = 0 for k in str(i): if k in '369': cnt += 1 if cnt == 0: result = f'{i}' else: result = '-'*cnt print(f'{result}', end=' ')

SWEA-농작물 수확하기 (2805) [내부링크]

# 농장의 크기는 항상 홀수 # 수확은 항상 농장의 크기에 맞는 정사각형 마름모 형태로만 가능 T = int(input()) for tc in range(1, T+1): N = int(input()) farm = [list(map(int,input())) for _ in range(N)] result = 0 middle = N//2 for i in range(middle+1): for k in range(middle-i, middle+i+1): result += farm[i][k] for i in range(middle): for k in range(i+1, N-i-1): result += farm[i+middle+1][k] print(f'#{tc} {result}')

SWEA-문제 제목 붙이기 (7087) [내부링크]

# 제목의 가장 앞 글자에 대문자 A~Z가 순서대로 등장 # 중간에 하나라도 안들어가면 제목 중단 T = int(input()) for tc in range(1, T+1): N = int(input()) arr = [input() for _ in range(N)] arr.sort() alpha = ['']*25 second_alpha = ['A'] cnt = 1 for i in range(1, 26): alpha[i-1] = chr(i+65) if arr[0][0] != 'A': cnt = 0 print(f'#{tc} {cnt}') continue for i in range(0, len(arr)): if arr[i][0] not in second_alpha and arr[i][0] == alpha[0]: cnt += 1 second_alpha.append(alpha.pop(0)) print(f'#{tc} {cnt}')

SWEA-영준이의 카드 카운팅 (4047) [내부링크]

# 이미 겹치는 카드를 가지고 있다면 오류를 출력 T = int(input()) for tc in range(1,T+1): # 무늬 (S,D,H,C)+숫자 arr = input() arr_dict = {'S':0,'D':1,'H':2,'C':3} arr_lst = [[] for _ in range(4)] for i in range(0, len(arr)-2, 3): if arr[i+1] != '0': if int(arr[i+1]+arr[i+2]) in arr_lst[arr_dict[arr[i]]]: print(f'#{tc} ERROR', end='') break arr_lst[arr_dict[arr[i]]].append(int(arr[i + 1] + arr[i + 2])) else: if int(arr[i+2]) in arr_lst[arr_dict[arr[i]]]: print(f'#{tc} ERROR', end='') break arr_lst[arr_dict[arr[i]]].appen

SWEA-원재의 메모리 복구하기 (1289) [내부링크]

import sys sys.stdin = open('원재의 메모리 복구하기.txt','r') # 원래 상태가 주어질 때 초기화 상태에서 돌아가는데 몇 번 고쳐야 하는지 # bit를 고르면 그 뒤는 전부 같은 수로 바뀐다. T = int(input()) for tc in range(1, T+1): # 결과로 나올 리스트 n_lst = list(map(int, input())) # 처음 리스트 arr = [0]*len(n_lst) # 결과 리스트 길이 N = len(n_lst) # 첫 리스트 길이 M = len(arr) i = 0 cnt = 0 while i <= N-1: if n_lst[i] != arr[i]: if n_lst[i] == 1: for x in range(i, len(arr)): arr[x] = 1 cnt += 1 if arr == n_lst: break else: for x in range(i, len(arr)): arr[x] = 0 cnt += 1 if arr ==

SWEA-정곤이의 단조 증가하는 수 (6190) [내부링크]

# 각 숫자의 자릿수가 단순하게 증가하는 수 # 양의 정수 N개가 주어진다. # 정수 N개 중 2개를 곱해서 단조 증가하는 수를 구하고 최댓값을 출력 T = int(input()) for tc in range(1, T+1): N = int(input()) arr = list(map(int,input().split())) result = [] max_num = 0 # 곱셈을 리스트에 저장 for i in range(N-1): for j in range(i+1, N): result.append(str(arr[i]*arr[j])) for i in range(len(result)): for j in range(len(result[i])-1): if int(result[i][j]) > int(result[i][j+1]): break else: if max_num < int(result[i]): max_num = int(result[i]) if max_num == 0: max_num = -1

SWEA-패턴 마디의 길이 (2007) [내부링크]

# 마디의 길이를 출력 T = int(input()) for tc in range(1, T+1): arr = input() word = f'{arr[0]}' for i in range(1,len(arr)-1): if arr[i] != word[0]: word += arr[i] elif arr[i] == word[0] and arr[i+1] != word[1]: word += arr[i] else: break print(f'#{tc} {len(word)}')

SWEA-퍼펙트 셔플 (3499) [내부링크]

# 퍼펙트 셔플하면 어떤 순서가 되는지 출력 # N이 홀수이면 교대로 놓을 때 먼저 놓는 쪽에 한장 더 들어간다. T = int(input()) for tc in range(1,T+1): N = int(input()) arr = input().split() result = ['']*N if N % 2: for i in range(N // 2): result[i * 2 + 1] = arr[N // 2 + i+1] result[i * 2] = arr[i] else: result[-1] = arr[N//2] else: for i in range(N//2): result[i*2+1] = arr[N//2+i] result[i*2] = arr[i] print(f'#{tc}', *result)

몸을 위한 투자 [내부링크]

2022년 9월 18일 최근에 의자에 앉아있는 시간이 많아졌다. 장시간 의자에서 생활을 하니 의자의 내구성이 많이 약해져 내 허리에도 조금씩 무리가 생기기 시작했다. 바른 자세를 유지하기 위해 노력하지만 의자가 버텨주질 못하여 고민 끝에 좋은 의자 하나를 구입하였다. 몇 주 전에는 돈이 아깝다고 생각해 구입을 미루었지만 몸이 많이 힘들어 구입을 결정했다. 의자를 산 김에 발을 올릴 수 있는 받침대도 하나 구입하였다. 아직 의자가 배송 중이라 후기는 다음 주쯤에 올려야겠다. PM 1:30

SWEA-Flatten(1208) [내부링크]

#상자를 높은 곳에서 낮은 곳으로 옮기는 방식 #평탄화 잡업을 하면 최고 높이와 최저 높이차 1 for tc in range(1,11): dump_num = int(input()) heigh = list(map(int,input().split())) max_heigh = 0 min_heigh = 0 result = -1 # 덤프 횟수가 남아도 평탕화가 끝나면 끝 while True: # for i in range(len(heigh)-1,0,-1): # for j in range(0,i): # if heigh[j] > heigh[j+1]: # heigh[j], heigh[j+1] = heigh[j+1], heigh[j] heigh.sort() if dump_num == 0: result = (heigh[-1] - heigh[0]) break if (heigh[-1] - heigh[0]) <= 1: result = (heigh[-1] - heigh[0]) break else: dump_

SWEA-Sum(1209) [내부링크]

# 2차원 배열이 주어짐 # 각 행의 합, 각 열의 합, 각 대각선의 합 중 최댓값을 구함 # 10개의 테스트 케이스 import sys sys.stdin = open('sum_input.txt', 'r') for tc in range(1, 11): N = int(input()) # 2차원 배열을 받음 arr = [list(map(int, input().split())) for _ in range(100)] num = len(arr) max_sum = 0 # 행의 최댓값을 구함 for i in range(num): sum_num = 0 for j in range(num): sum_num += arr[i][j] if max_sum < sum_num: max_sum = sum_num # 행의 최댓값과 열의 최댓값을 구해서 비교 for j in range(num): sum_num = 0 for i in range(num): sum_num += arr[i][j] if max_sum < su

SWEA-ladder (1210) [내부링크]

# 어느 사다리를 고르면 X표시에 도착하게 되는지 구함 # 출발점 x = 100 # 사다리 1 도착지점 2 # 테스트 케이스 T import sys from unittest import result sys.stdin = open('ladder.txt', 'r') for tc in range(1,11): T = int(input()) arr = [list(map(int,input().split())) for _ in range(100)] # 아래 왼 오 위 ti = [1,0,0,-1] tj = [0,-1,1,0] # 도착지에서 위로 올라간다. x = 99 y = 0 move = 3 # 도착지 2에서 출발한다. for i in range(100): if arr[99][i] == 2: y = i while x != 0: x += ti[move] y += tj [move] if 0<= y - 1 and arr[x][y-1] != 0 and move != 2: move = 1 elif y +

SWEA-GNS(1221) [내부링크]

# 숫자를 문자열로 나타내는 행성이 있다. import sys sys.stdin = open('GNS_test_input.txt','r') # 첫 줄에 테스트 케이스의 개수가 주어진다. T = int(input()) for tc in range(1,T+1): # #기호와 함께 테스트 케이스의 번호가 주어지고 공백문자 후 테스틑 케이스의 길이가 주어진다. C, N = map(str,input().split()) # 테스트 케이스가 주어진다. TC = input() char = [] num_arr = ['ZRO', 'ONE', 'TWO', 'THR', 'FOR', 'FIV', 'SIX', 'SVN', 'EGT', 'NIN'] # 문자를 숫자 문자로 바꿈 for i in range(len(num_arr)): TC = TC.replace(num_arr[i],f'{i}') # 숫자를 비교해서 문자로 다시 변경하고 새로운 리스트에 저장 for i in range(len(num_arr)): fo

SWEA-글자수(4865) [내부링크]

# 첫 줄에 테스트 케이스 개수 T import sys sys.stdin = open('4864.txt','r') T = int(input()) for tc in range(1,T+1): str1 = input() str2 = input() result = {} max_num = 0 for i in str2: if result.get(i): result[i] += 1 else: result[i] = 1 for i in str1: if max_num < result[i]: max_num = result[i] print(f'#{tc} {max_num}')

SWEA-문자열 비교(4864) [내부링크]

# 문자열 1과 2가 주어짐 # 문자의 일치하는 부분이 존재하면 1, 아니면 0 # 첫 줄에 테스트 T import sys sys.stdin = open('4864.txt','r') T = int(input()) for _ in range(1,T+1): str1 = input() str2 = input() for i in range(len(str2)): if str2[i] == str1[0] and str2[i:i+len(str1)] == str1: result = 1 break else: result = 0 print(f'#{_} {result}')

SWEA-회문(4861) [내부링크]

# 회문을 찾아라 # 첫 줄에 테스트 케이스 갯수 T import sys sys.stdin = open('4861.txt','r') T = int(input()) for tc in range(1,T+1): # 크기 N * N, 회문 길이 M N, M = map(int,input().split()) strs = [input() for _ in range(N)] result = '' for i in strs: for j in range(N-M+1): for k in range(M//2): if i[j+k] != i[j+M-k-1]: break else: for x in range(M): result += i[j+x] for i in range(N): for j in range(N-M+1): for k in range(M//2): if strs[j+k][i] != strs[j+M-k-1][i]: break else: for x in range(M): result += strs[j+x][i

SWEA-회문2(1216) [내부링크]

for tc in range(1,11): T = int(input()) arr = [input() for _ in range(100)] result = '' max_num = 0 N = 100 for i in range(N): M = 100 while M > 0: for j in range(N-M+1): for k in range(M//2): if arr[i][j+k] != arr[i][j+M-k-1]: break else: result = '' for x in range(M): result += arr[i][j+x] if max_num < len(result): max_num = len(result) M -= 1 for i in range(N): M = 100 while M > 0: for j in range(N-M+1): for k in range(M//2): if arr[j+k][i] != arr[j+M-k-1][i]: break else: result = '' for x in

SWEA-파스칼의 삼각형(2005) [내부링크]

# 테스트 케이스 T = int(input()) for tc in range(1, T+1): N = int(input()) print(f'#{tc}', end='') for i in range(N+1): for j in range(i): if i <= 2: print('1', end=' ') else: if j == 0 or j == i-1: print('1', end=' ') else: print(f'{i-1}', end=' ') print()

SWEA-괄호검사(4866) [내부링크]

# 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1, T+1): arr = list(map(str, input())) # ()를 저장 stack = [] # {}를 저장 result = 1 for i in arr: if '(' not in stack and i == ')': result = 0 break if '{' not in stack and i == '}': result = 0 break if i == '(' or i == '{': stack.append(i) if i == ')' and stack[-1] == '(': stack.pop() elif i == ')' and stack[-1] != '(': result = 0 break if i == '}' and stack[-1] == '{': stack.pop() elif i == '}' and stack[-1] != '{': result = 0 break if stack: result =

SWEA-그래프 경로(4871) [내부링크]

# 첫 줄에 테스트 케이스 # 둘째 줄에 V, E # 마지막 줄에 S G T = int(input()) for tc in range(1, T+1): V, E = map(int, input().split()) route = [[] for _ in range(V+1)] for i in range(E): a, b = map(int, input().split()) route[a].append(b) S, G = map(int, input().split()) top = -1 stack = [0]*V visited = [0]*(V+1) top += 1 stack[top] = S visited[S] = 1 result = 0 while top > -1: if stack[top] == G: result = 1 break for i in route[stack[top]]: if visited[i] == 0: visited[i] = 1 top += 1 stack[top] = i break else: to

SWEA-길찾기(1219) [내부링크]

import sys sys.stdin = open('find_road.txt','r') # A = 0, B = 99 # 첫 줄에는 테스트 케이스의 번호와 길의 총 개수 for tc in range(1, 11): T, V = map(int,input().split()) # 순서쌍이 주어진다. route = [[] for _ in range(100)] arr = list(map(int, input().split())) for i in range(0, len(arr), 2): route[arr[i]].append(arr[i+1]) # 시작점 top = -1 stack = [0]*100 visited = [0]*100 top += 1 stack[top] = 0 visited[0] = 1 result = 0 while top > -1: # 인접한 지점을 찾는다. if stack[top] == 99: result = 1 break for i in route[stack[top]]: if not

SWEA-반복문자 지우기(4873) [내부링크]

# 반복문자를 지운다. # 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1, T+1): strs = list(input()) # 문자열 검사 횟수 i = 0 while i < len(strs)-1: # 앞과 뒤가 같으면 둘다 제거 if strs[i] == strs[i+1]: strs.pop(i) strs.pop(i) # 다시 처음부터 검사 i = 0 i += 1 print(strs)

SWEA-종이붙이기(4869) [내부링크]

# 첫 줄에 테스트 케이스가 주어진다. # 가로 * 세로, 10*20과 20*20이 있음 # 세로는 20으로 정해짐 # N에 따라서 크기가 달라짐 T = int(input()) for _ in range(1, T+1): N = int(input()) arr = [1, 2, 5, 11] if N//10 < 4: i = N//10 -1 print(f'#{_} {arr[i]}') continue else: while len(arr) < N/10: result = 0 result = arr[-1]*arr[0] + arr[-2]*arr[1] arr.append(result) print(f'#{_} {arr[-1]}')

SWEA-간단한 소인수분해(1945) [내부링크]

# 첫 줄에는 테스트 케이스 T = int(input()) for tc in range(1, T+1): N = int(input()) a, b, c, d, e = 0, 0, 0, 0, 0 while N > 1: if not N % 2: N /= 2 a += 1 continue if not N % 3: N /= 3 b += 1 continue if not N % 5: N /= 5 c += 1 continue if not N % 7: N /= 7 d += 1 continue if not N % 11: N /= 11 e += 1 continue print(f'#{tc} {a} {b} {c} {d} {e}')

SWEA-삼성시의 버스 노선(6485) [내부링크]

# 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1, T+1): # 버스 노선 개수 N = int(input()) # A이상 B이하인 모든 정류장만을 다니는 버스 노선 nosion = [list(map(int, input().split())) for _ in range(N)] # 버스 정류장의 개수 P = int(input()) # C번 버스 C = [int(input()) for _ in range(P)] result = [0] * 5001 for i in range(len(C)): for j in range(N): if nosion[j][0] <= C[i] <= nosion[j][1]: result[i] += 1 print(f'#{tc}', *result[:P])

SWEA-쇠막대기 자르기(5432) [내부링크]

# 밑의 쇠막대기가 더 길다 # 끝점이 겹치도록 놓지는 않는다. # 레이저는 적어도 하나 존재한다 # 레이저는 쇠막대기의 양 끝점과 겹치지 않는다. # 레이저는 (), 쇠막대기의 왼쪽 끝은 : (, 오른쪽 끝은 : ) T = int(input()) for tc in range(1, T+1): arr = input() # 막대기를 저장하는 변수 stack = [] # 레이저 개수를 저장 # 막대기 숫자를 저장 result = 0 for i in range(len(arr)-1): if arr[i] == '(' and arr[i+1] != ')': stack.append(arr[i]) elif arr[i] == '(' and arr[i+1] == ')': result += len(stack) if not stack: cnt = 0 if arr[i] == ')' and arr[i-1] != '(': result += 1 stack.pop() else: if stack[0] == '(' an

SWEA-스도쿠 검증(1974) [내부링크]

import sys sys.stdin = open('1974.txt','r') # 9*9 # 겹치는 숫자가 없을 경우 1 아니면 0 출력 T = int(input()) for tc in range(1, T+1): # 스도쿠를 2차원 배열로 받음 arr = [list(map(int, input().split())) for _ in range(9)] # 스도쿠의 중복 숫자를 세는 변수 counts = [0] * 10 # 스도쿠의 중복 숫자가 있으면 저장하는 변수 result = [1, 1] is_sdoqu = 1 # 가로 세로의 중복 숫자를 구함 for i in range(9): for j in range(9): counts[arr[i][j]] += 1 counts[arr[j][i]] += 1 # 가로 세로랑 네모칸을 비교하기 위한 네모칸 구하는 for 문 for a in range(0,7,2): for b in range(0,7,2): for c in range(3): for d in

SWEA-어디에 단어가 들어갈 수 있을까(1979) [내부링크]

import sys sys.stdin = open('1979.txt','r') # 특정 길이 K를 갖는 단어가 들어갈 수 있는 자리의 수를 출력 # 5 <= N <= 15 # 2<= k <= N T = int(input()) for tc in range(1, T+1): N, K = map(int,input().split()) arr = [input().split() for _ in range(N)] cnt = 0 result = 0 for i in range(N): for j in range(N): if arr[i][j] == '1': cnt += 1 elif arr[i][j] == '0' and cnt == K: result += 1 cnt = 0 else: cnt = 0 if cnt == K: result += 1 cnt = 0 for i in range(N): for j in range(N): if arr[j][i] == '1': cnt += 1 elif arr[j][i] ==

SWEA-파리퇴치(2001) [내부링크]

# 파리 영역 5<= N <= 15 # 파리채 영역 2<= M <=N # 파리 갯수는 30이하 T = int(input()) for tc in range(1,T+1): N, M = map(int,input().split()) arr = [list(map(int,input().split())) for _ in range(N)] max_num = 0 sum_num = 0 for i in range(N-M+1): sum_num = 0 for j in range(N-M+1): sum_num = 0 for k in range(M): for l in range(M): sum_num += arr[i+k][j+l] if max_num < sum_num: max_num = sum_num print(f'#{tc} {max_num}')

SWEA-계산기2(1223) [내부링크]

def step1(inOrder): isp = {'+': 1, '*': 2, '(': 0} icp = {'+': 1, '*': 2, '(': 3} order = {'+': 1, '*': 2} ST = [] postOrder = [] for token in inOrder: if token.isdecimal(): postOrder.append(token) else: # 왼쪽 괄호가 있는 경우 # isp[ST[-1]] >= icp[token] # 스택에 있는 거랑 token이랑 우선순위를 생각 while len(ST) > 0 and order[ST[-1]] >= order[token]: postOrder.append(ST.pop()) ST.append(token) while ST: postOrder.append(ST.pop()) # if len(ST) and order[ST[-1]] < order[token]: # ST.append(token) # else: # while len(ST)

SWEA-계산기3(1224) [내부링크]

def CHANGE(arr): stack = [] words = '' for i in arr: if i in '(*+)': if i == ')' and stack: while stack[-1] != '(' and stack: words += stack.pop() stack.pop() continue if stack and stack[-1] == '+' and i == '*': stack.append(i) elif i == '(': stack.append(i) continue else: if stack and stack[-1] != '(': words += stack.pop() stack.append(i) else: words += i return words def cal(word): stack = [] for i in word: if i not in '*+': stack.append(i) else: if i == '*' and stack: stack.append(int(stack.p

SWEA-암호생성기(1225) [내부링크]

# 8개의 숫자를 입력 받음 # n번째 수는 n만큼 감소하고 뒤로 보내짐 # 숫자가 감소할 때 0보다 작아지는 경우 0으로 유지되고 종료 # 주어진 수는 integer 범위를 넘지 않음 # 마지막 배열은 모두 한자리 수로 구성 # 큐를 이용하여 암호를 확인 def Q(N_lst): cnt = 1 result = 0 while not result: # 5회를 반복하면 1 싸이클 while cnt <= 5: queue = [0] * 8 # 첫 번째 자리를 제외하고 큐에 저장 for i in range(1, 8): queue[i-1] = N_lst[i] # 첫 번째 자리가 0보다 작아지면 종료 if N_lst[0]-cnt <= 0: queue[-1] = 0 result = 1 return queue # 아니면 cnt를 빼고 마지막 자리에 저장 queue[-1] = (N_lst[0]-cnt) N_lst = queue cnt += 1 cnt = 1 # 첫 줄에 테스트 케이스 번호 for tc

SWEA-미로1(1226) [내부링크]

def bfs(i,j): # 가로 세로 visited[i][j] = 1 front = rear = -1 rear += 1 q[rear] = (i,j) while front != rear: front += 1 i,j = q[front] #오 밑 왼 위 if maze[i][j] == 3: return 1 for di, dj in [[0,1],[1,0],[0,-1],[-1,0]]: ni = i + di nj = j + dj if 0<= ni < 16 and 0<= nj < 16 and not visited[ni][nj] and maze[ni][nj] != 1: visited[ni][nj] = 1 rear += 1 q[rear] = ni,nj return 0 # 테스트 케이스 for tc in range(1,11): TC = int(input()) # 1 = 벽, 0 = 길, 2 = 출발점, 3 = 도착점 maze = [list(map(int,input())) for _ in range(1

SWEA-달란트2(1265) [내부링크]

import sys sys.stdin = open('달란트.txt','r') # 테스트 케이스 T = int(input()) for tc in range(1, T+1): N, P = map(int, input().split()) num_lst = [N // P] * P rest = N % P result = 1 for i in range(rest): num_lst[i] += 1 for i in range(len(num_lst)): result *= num_lst[i] print(f'#{tc} {result}')

SWEA-사칙연산(1232) [내부링크]

# 10개의 테스트 케이스 for tc in range(1,11): # 첫 줄에는 정점의 개수 N N = int(input()) # 그 다음 N 줄에 정점의 정보 # 정점이 정수면 정점 번호와 양의 정수 # 연산자이면 정점 번호, 연산자, 왼쪽, 오른쪽 자식의 정점 번호 # 정점 번호는 1부터 N까지의 정수, 루트 정점의 번호는 항상 1 arr = [list(input().split()) for _ in range(N)] lst = [0] perent = [0]*(N+1) # 정점 번호별로 값을 새리스트에 저장 for i in range(N): lst.append(arr[i][1]) if len(arr[i]) == 4: # 자식 - 부모를 연결하는 리스트 perent[int(arr[i][2])] = int(arr[i][0]) perent[int(arr[i][3])] = int(arr[i][0]) # 계산을 위한 변수 cal = 0 # 자식에게 연결된 부모를 계산하는 과정 for j

SWEA-subtree [내부링크]

# 첫 줄에 테스트 케이스 def preorder(N): global cnt if N: cnt += 1 preorder(ch1[N]) preorder(ch2[N]) return cnt T = int(input()) for tc in range(1,T+1): # 간선의 개수 E와 N E, N = map(int,input().split()) # E개의 부모 자식 노드 번호 쌍 node = list(map(int,input().split())) ch1 = [0] * (E+2) ch2 = [0] * (E+2) cnt = 0 for i in range(0,E*2,2): p, c = node[i], node[i+1] if not ch1[p]: ch1[p] = c else: ch2[p] = c print(f'#{tc} {preorder(N)}')

SWEA-노드의 합 [내부링크]

def postorder(v): if v > N: return 0 l_result = postorder(2*v) r_result = postorder(2*v+1) tree[v] += l_result + r_result return tree[v] # 테스트 케이트 T T = int(input()) for tc in range(1,T+1): # 노드의 개수 N, 리프 노드의 개수M, 값을 출력할 노드 번호 L N, M, L = map(int,input().split()) # M개의 줄에 걸쳐 리프 노드 번호, 자연수 tree = [0] * (N+1) for i in range(M): L_num, nat = map(int,input().split()) tree[L_num] = nat print(tree) # L, R = 0, 0 result = postorder(1) print(tree[L])

SWEA-이진 합 [내부링크]

# 이진 최소힙에 저장 # 마지막 노드의 조상 노드에 저장된 정수의 합 def heap_push(n): global heap_count heap_count += 1 heap[heap_count] = n c = heap_count p = c // 2 while heap_count and heap[c] < heap[p]: heap[c], heap[p] = heap[p],heap[c] c = p p = c // 2 # 테스트 케이스의 수 T = int(input()) for tc in range(1,T+1): # 테스트 케이스의 별로 N N = int(input()) # 수를 저장할 힙리스트 heap = [0]*(N+1) # 힙의 마지막 인덱스 heap_count = 0 # 1000000 이하인 서로 다른 N개의 자연수 number = list(map(int,input().split())) for i in number: heap_push(i) # 마지막 노드의 조상 노드에 저장된 정수의

SWEA-이진탐색 [내부링크]

# N이 주어졌을 때 완전 이진 트리로 만든 # 이진 탐색 트리의 루트에 저장된 값과 # N/2번 노드에 저장된 값을 출력하는 프로그램 # 첫 줄에 테스트 케이스 def inorder(v): global number if v < N+1 and v: inorder(2*v) arr[v] = number number += 1 inorder(2*v+1) T = int(input()) for tc in range(1,T+1): # 테스트 케이스의 별로 N이 주어짐 N = int(input()) arr = [_ for _ in range(N+1)] number = 1 inorder(1) print(f'#{tc} {arr[1]} {arr[N//2]}')

SWEA-세제곱근을 찾아라 [내부링크]

# 양의 정수 N에 대해 N = x^3가 되는 양의 정수 x # 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1, T+1): # 하나의 정수 N N = int(input()) # 1/3제곱한 것을 result에 담는다. result = N**(1/3) # 부동소수점 검사를 실시해서 오차가 많이 작으면 반올림해서 출력 if abs(round(result) - result) <= 1e-9: print(f'#{tc} {round(result)}') # 아니면 -1을 출력 else: print(f'#{tc} -1')

SWEA-재미있는 오셀로 게임 [내부링크]

# 보드는 4*4, 6*6, 8*8 # 첫 줄에 테스트 케이스 T T = int(input()) for tc in range(1,T+1): # 한변의 길이 N, 플레이어가 돌을 놓는 횟수 M N, M = map(int,input().split()) # M줄에는 돌을 놓을 위치와 돌의 색 # 1이면 흑, 2이면 백 board = [[0] * N for _ in range(N)] # 초기 보드 상태 board[N // 2 - 1][N // 2 - 1], board[N // 2][N // 2] = 2, 2 board[N // 2 - 1][N // 2], board[N // 2][N // 2 - 1] = 1, 1 # 돌의 위치에서 8방향 탐색 dr = [-1,-1,0,1,1,1,0,-1] dc = [0,1,1,1,0,-1,-1,-1] # M번의 게임을 반복 for i in range(M): r, c, player = map(int, input().split()) # 받은 위치를 인덱스 값으

SWEA-정사각형 방 [내부링크]

# N^2개의 방이 N*N형태로 있다. # i,j에는 1 이상 N^2 이하의 수 Aij가 적혀있다. # 이 숫자는 모든 방에 대해 서로 다르고 다른 방으로 이동할 수 있다. # 이동하려는 방이 존재해야 하고, 이동하려는 방에 적힌 숫자가 현재 방에 # 적힌 숫자보다 정확히 1 더 커야한다. # 첫 번째 줄에 테스트 케이스 T = int(input()) for tc in range(1,T+1): # 첫 번째 줄에는 정수 N N = int(input()) # 다음 N개의 줄에는 N개의 정수 room = [list(map(int, input().split())) for _ in range(N)] di = [0,1,0,-1] dj = [1,0,-1,0] max_num = 0 lst = [] for i in range(N): for j in range(N): r, c = i, j cnt = 1 while True: for k in range(4): ni = i + di[k] nj = j +

SWEA-홈 방범 서비스 [내부링크]

# 운영 비용 = K*K + (K - 1)*(K - 1) # 서비스를 제공받는 집들은 각각 M의 비용을 지불할 수 있다. # 도시의 크기 5<= N <= 20 # 지불 비용 1<= M <= 10 # 집이 있는 위치는 1, 나머지는 0 # 손익계산하는 함수 def service(r,c,k): cnt = 0 colume = -1 for x in range(r-(k-1),r+k): if x <= r: colume += 1 for y in range(c-colume,c+colume+1): if 0<= x < N and 0<= y < N and city[x][y]: cnt += 1 elif x > r: colume -= 1 for y in range(c-colume,c+colume+1): if 0<= x < N and 0<= y < N and city[x][y]: cnt += 1 return cnt T = int(input()) for tc in range(1,T+1): # 도시의 크기 N,

0.1 컴퓨팅 사고력 [내부링크]

algorithm day8 컴퓨팅 사고력 0.1.1 서론 명제 참이나 거짓을 알 수 있는 식이나 문장 p, q, r로 표현 진릿값 참이나 거짓을 표현 T, F 또는 1, 0 부정(NOT) p가 명제일 때, 명제의 진릿값이 반대 ~p 또는 ¬p로 표기 (not p 또는 p의 부정으로 읽음) 논리 곱 AND p,q가 명제일 때 p,q 모두 참일 때만 참이 되는 명제 p^q (p and q, q 그리고 q) 논리 합 OR p, q가 명제일 때 p,q 모두 거짓일 때만 거짓이 되는 명제 p V q (p or q, p 또는 q) 배타적 논리합 XOR p, q가 명제일 때 p, q 중 하나만 참일 때 참이 되는 명제 p⊕q (p xor q) 합성 연산자 우선 순위 항진명제 : 진릿값이 항상 참 모순명제 : 진리 값이 항상 거짓 사건명제 : 항진명제도 모순명제도 아닌 명제 조건명제 p, q가 명제일 때, 명제 p가 조건(또는 원인), q가 결론(또는 결과)로 제시되는 명제 p → q (p이면 q

0.2 컴퓨팅 사고력 [내부링크]

algorithm day8 컴퓨팅 사고력

SWEA-단순 2진 암호코드 [내부링크]

# 암호코드는 8개의 숫자 (여기에 조건을 적어놓았는데 깜빡해서 문제를 더 어렵게 풀었다..) # 올바른 암호코드 (홀수 자리의 합*3) + (짝수 자리의 합)이 10의 배수 # 스캐너는 암호코드 1개가 포함된 직사각형 배열을 읽는다. # 암호코드 이외의 부분은 전부 0 # 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1,T+1): # 배열의 세로 크기 N, 배열의 가로 크기 M # 1<= N <=50, 56<=M<=100 N, M = map(int,input().split()) # N개의 줄에 걸쳐 직사각형 배열 password_lst = [list(map(int,input())) for _ in range(N)] # 암호가 있는 행을 저장하는 변수 row = 0 # 1이 나오는 열을 찾는다. for i in range(N): for j in range(M): if password_lst[i][j]: row = i break if row: br

0.1 SW 문제 해결 [내부링크]

algorithm day9 SW 문제 해결 0.1.1 SW 문제 해결 프로그래밍 하기 위한 제약 조건과 요구 사항 프로그래밍 언어의 특성 프로그램이 동작할 HW와 OS에 관한 지식 라이브러리들의 유의 사항들 프로그램이 사용할 수 있는 최대 메모리 사용자 대응 시간 제한 재사용성이 높은 간결한 코드 문제 해결 과정 문제를 읽고 이해한다. 문제를 익숙한 용어로 재정의 한다. 어떻게 해결할지 계획을 세운다. 계획을 검증한다. 프로그램으로 구현한다. 어떻게 풀었는지 돌아보고, 개선할 방법이 있는지 찾아본다. 직관과 체계적인 접근 비슷한 문제를 풀어본 적이 있던가 단순한 방법에서 시작할 수 있을까 문제를 단순화 할 수 있을까 그림으로 그려 볼 수 있을까 수식으로 표현 할 수 있을까 문제를 분해 할 수 있을까 뒤에서 부터 생각해서 문제를 풀 수 있을까 특정 형태의 답만 고려할 수 있을까 0.1.2 복잡도 분석 알고리즘의 효율 공간적 효율성과 시간적 효율성 공간적 효율성은 연산량 대비 얼마나 적

0.2 SW 문제 해결 [내부링크]

algorithm day9 SW 문제 해결 0.2.1 비트 연산 비트 연산자 & : 비트 단위로 AND 연산을 한다. 특정 bit를 0으로 만들 때 사용 (비트 검사) | : 비트 단위로 OR 연산을 한다. 특정 bit를 1로 만들 때 사용 ^ : 비트 단위로 XOR 연산을 한다. (같으면 0 다르면 1) 특정 bit를 반전 시킬 때 사용 ~ : 단항 연산자로서 피연산자의 모든 비트를 반전 시킨다. not하고 invert는 다르다. << : 피연산자의 비트 열을 왼쪽으로 이동시킨다. '>>' : 피연산자의 비트 열을 오른쪽으로 이동시킨다. 비트 연산 1<<n 2^n의 값을 갖는다. 원소가 n개일 경우의 모든 부분 집합의 수를 의미 Power set(모든 부분 집합) 공집합과 자기 자신을 포함한 모든 부분 집합 각 원소가 포함되거나 포함되지 않는 2 가지 경우의 수를 계산하면 모든 부분 집합의 수가 된다. i & (1<<j) 계산 결과는 i의 j번째 비트가 1인지 아닌지 의미한다. i

SWEA-이진수(5185) [내부링크]

import sys sys.stdin = open('이진수(5185).txt','r') # 16진수가 주어지면 2진수로 바꾸는 프로그램 # 앞자리 0도 반드시 출력 # 16진수를 2진수로 바꾸는 함수 def binary(num): if num < 2: return str(num%2) return str(binary(num//2)) + str(num%2) # 테스트 케이스 T = int(input()) for tc in range(1,T+1): # 자리수 N, N자리 16진수 N, M = input().split() # 16진수 영어를 숫자로 매핑하는 딕셔너리 M_dic = {'A':10, 'B':11, 'C':12, 'D':13, 'E':14, 'F':15} # 결과 값 result = '' for i in M: # 문자가 나오면 숫자로 바꿔서 변환 if i in M_dic: i = M_dic[i] # 2진수로 바꾸고 binary(int(i)) # 만약 2진수의 길이가 4의 배수가

SWEA-이진수2(5186) [내부링크]

# 0<= N < 1 십진수를 이진 수로 변경 # 12자리 이내에 이진수로 표현할 수 있으면 출력 # 아니면 overflow를 출력 # 테스트 케이스 T = int(input()) for tc in range(1, T + 1): N = input() # .에 인덱스를 계산 K = N.index('.') result = '' while True: # .의 인덱스 계산 K = N.index('.') # 소수만 본다 number = N[K + 1:] # 소수를 만든다 new_number = float('0' + '.' + number) next_number = new_number * 2 N = str(next_number) # 소수점 앞자리 저장 result += N[0] if N == '1.0': break elif len(result) > 12: result = 'overflow' break print(f'#{tc} {result}')

SWEA-베이비진 게임 [내부링크]

# 0~9까지인 숫자 카드 4세트를 섞은 후 6개의 카드를 고름 # 연속인 숫자가 3개 이상이면 run, 같은 숫자가 3개 이상이면 triple # 교대로 한 장씩 카드를 가져감, 먼저 run이나 triple이 되는 사람이 승자 # 무승부는 0 # 테스트케이스 T T = int(input()) for tc in range(1,T+1): data = list(map(int,input().split())) player1 = [0]*10 player1_run = [] player2 = [0]*10 player2_run = [] # run을 확인하기 위한 딕셔너리 num_dic = { 0:'012', 1:'123', 2:'234', 3:'345', 4:'456', 5:'567', 6:'678', 7:'789' } result = 0 for i in range(len(data)): # 수를 하나씩 가져간다 if not i%2: player1[data[i]] += 1 player1_run.ap

SWEA-전자키트 [내부링크]

def solve(start,v,cnt): global minV if cnt == N and not check[-1] and minV > v: minV = v return else: # v값이 최소값보다 커지는 순간 다시 돌아감 if v > minV: return # 첫 번째 행부터 검사 for i in range(N): # 만약 값이 0이 아니고 방문한 적이 없으면 if data[start][i] and i not in check: # 방문 체크 check.append(i) # 다음 행으로 넘어감 solve(i,v+data[start][i],cnt+1) # 방문한 것을 초기화 check.pop() # 각 구역을 한 번씩만 방문하고 돌아왔을 때 배터리 사용량의 최소를 구함 # 테스트 케이스 T = int(input()) for tc in range(1,T+1): N = int(input()) data = [list(map(int,input().split())) for _ in ran

SWEA-최소합 [내부링크]

# N*N 칸, 오른쪽 아랫쪽만 이동 가능 # 최소합 구하기 def solve(r, c, v): global result if r == N or c == N: return else: if v > result: return # 오른쪽 or 아랫쪽으로만 이동 solve(r+1, c, v+data[r][c]) solve(r, c+1, v+data[r][c]) # 최소합 구하기 if r == N-1 and c == N-1: if result > v: result = v return T = int(input()) for tc in range(1, T+1): N = int(input()) data = [list(map(int, input().split())) for _ in range(N)] # 최솟값을 구하는 변수 result = 5000000 solve(0,0,0) print(f'#{tc} {result+data[N-1][N-1]}')

SWEA-컨테이너 운반 [내부링크]

# N개의 컨테이너를 M대의 트럭으로 운반 # 트럭당 한 개의 컨테이너를 운반할 수 있음, 적재량을 초과하면 운반 x # M대의 트럭이 편도로 한번만 이동 # 테스트케이스 T = int(input()) for tc in range(1,T+1): # 컨테이너 수 N, 트럭 수 M N, M = map(int,input().split()) # N개의 화물의 무게 Wi = list(map(int,input().split())) # M개 트럭의 적재용량 ti = list(map(int,input().split())) # 화물의 무게를 정렬 Wi.sort(reverse=True) # 트럭의 적재 용량을 정렬 ti.sort(reverse=True) # 화물의 무게를 나타냄 weith = 0 # 옮긴 총 무게를 나타내는 변수 sum_weith = 0 # 옮긴 횟수를 나타냄 cnt = 0 while True: # 가장 큰 무게가 적재 용량보다 작거나 같으면 # 옮겼다는 의미, 트럭에서 1개를 뺀다.

SWEA-화물도크 [내부링크]

T = int(input()) for tc in range(1, T + 1): N = int(input()) data = [list(map(int, input().split())) for _ in range(N)] # 끝나는 시간 순으로 정렬 data.sort(key=lambda x: x[1]) e = data[0][1] cnt = 1 # 첫 번째 작업 중 다음 작업의 시작 시간이 있으면 패스 아니면 갯수 세기 for i in range(1, N): if data[i][0] >= e: e = data[i][1] cnt += 1 print(f'#{tc} {cnt}')

SWEA-격자판의 숫자 이어 붙이기 [내부링크]

# 4*4 크기의 격자판, 0~9 사이의 숫자가 적혀있다. # 임의의 위치에서 시작, 4방향으로 인접한 격자로 총 여섯 번 이동후 # 이어붙이면 7자리 수 # 한 번 거쳤던 격자 칸을 다시 거쳐도 된다. # 완전 탐색하는 재귀 함수 def solve(r,c,cnt,char): dr = [0,1,0,-1] dc = [1,0,-1,0] if cnt == 7: check.append(char) return elif r < 0 or c < 0 or r > 3 or c > 3: return else: for i in range(4): nr = r + dr[i] nc = c + dc[i] solve(nr,nc,cnt+1,char+data[r][c]) # 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1,T+1): data = [input().split() for _ in range(4)] check = [] # 완전 탐색 for i in range(4): f

SWEA-디저트 카페 [내부링크]

# 디저트 카페를 방문 # 대각선으로만 이동 가능 # 같은 숫자의 카페는 갈 수 없음 # 투어를 마치고 다시 돌아와야 한다. # 디저트를 먹을 수 없는 경우 -1 # 테스트 케이스 def solve(r,c,i): global maxV dr = [-1,1,1,-1] dc = [1,1,-1,-1] # 출력 조건 if 0<= r <N and 0<= c < N and visited and (r,c,data[r][c]) == visited[0] and maxV < len(visited) and len(visited) >= 3: maxV = len(visited) return # 탈출 조건 elif r < 0 or c < 0 or r >= N or c >= N or check[data[r][c]] >= 1 or (r,c,data[r][c]) in visited: return else: # 대각선 한 방향으로만 이동하다가 탈출 조건을 만나면 방향을 바꾼다. for q in range(i,4):

SWEA-미생물 격리 [내부링크]

# 정사각형 구역 안에 K개의 미생물 # 가로 * 세로 = N*N # 가장자리 부분에 약품 # 군집의 위치, 미생물 수, 이동 방향이 주어진다. # 1시간마다 상하좌우 이동 # 이동 후 약품이 칠해진 셀에 도착하면 절반이 없어짐, 이동 방향이 반대 # 홀 수 = // # 한 셀에 두 개 이상의 군집이 모이면 합쳐짐, 이동 방향은 수가 많은 미생물 군집의 방향 # 정사각형, 한 변의 셀의 개수 5<= N <= 100 # 미생물 군집의 개수 5<=K<=1000 # 격리 시간 1<=M<=1000 # 미생물 수 1이상 10000 이하 T = int(input()) for tc in range(1,T+1): # 한 변 N, 격리 시간 M ,군집 개수 K N,M,K = map(int,input().split()) # c,r,미생물 수,이동 방향 arr = [list(map(int,input().split())) for _ in range(K)] # 상 하 좌 우 dr = [-1,1,0,0] d

SWEA-장훈이의 높은 선반 [내부링크]

# 각 점원의 키는 Hi, 높이 B # 각 점원의 키 합이 B가 되어야 한다. # 부분 집합을 구해서 값을 비교하는 함수 def solve(num): global minV if num == N: result = 0 # 부분 집합의 결과를 키와 매치하여 값을 비교하는 과정 for i in range(N): if part_set[i]: result += Hi[i] if result >= B and result - B < minV: minV = result - B return else: # 부분 집합을 구하는 부분 for i in range(2): part_set[num] = i solve(num+1) # 첫 번째 줄에 테스트 케이스 T T = int(input()) for tc in range(1,T+1): # 첫 번째 줄에 두 정수 N, B N, B = map(int,input().split()) Hi = list(map(int,input().split())) # 점원의 키를 큰 순으

SWEA-정식이의 은행 업무 [내부링크]

# 2진수, 3진수를 한 자리만 잘못 기억 # 두 수가 같은 수를 출력 # 2진수를 10진수로 바꾸는 함수 def change_bi(arr): result = 0 for i in range(len(arr)-1,-1,-1): if arr[len(arr)-i-1] == '1': result += 2**i return result # 3진수를 10진수로 바꾸는 함수 def change_thi(arr): result = 0 for i in range(len(arr)-1,-1,-1): if arr[len(arr)-i-1] == '2': result += 3**i*2 elif arr[len(arr)-i-1] == '1': result += 3 ** i return result # 테스트 케이스 T = int(input()) for tc in range(1,T+1): data = [list(input()) for _ in range(2)] result = [] for i in range(2):

SWEA-암호코드 스캔 [내부링크]

# 암호코드 규칙 # 1. 8개의 숫자 # 2. 앞 7자리는 상품 고유의 번호, 마지막 자리는 검증 코드 # 3. (짝수자리 합)*3 + 홀수자리 합 + 검증코드 = 10의 배수가 되어야 한다. # 스캐너 성능 # 1. 세로 2000, 가로 500 이하의 크기 # 2. 비정상적인 암호코드가 포함될 수 있다. # 3. 배열은 16진수, 2진수로 변환하여 정보를 확인해야한다. # 4. 정상적인 암호코드들을 판별한 뒤 숫자들의 합을 출력 # 규칙 # 1. 암호코드들이 붙어있는 경우는 없다. # 2. 모든 암호코드는 8개의 숫자 # 3. 암호코드의 세로 길이는 5~100칸 # 4. 암호코드의 가로 길이는 두께에 따라 달라짐, 두께가 가장 가는 경우 # 숫자 하나가 차지하는 길이는 7칸 # 5. 숫자 밑의 수는 비율을 의미 # 6. 선이 굵어질 경우 56의 배수 길이를 갖는다. T = int(input()) dic = {(3,2,1,1) : '0' , (2,2,2,1): '1', (2,1,2

0.1 반복, 재귀, 완전 검색 [내부링크]

algorithm day10 반복, 재귀, 완전 검색 0.1.1 반복과 재귀 개념 반복과 재귀는 유사한 작업을 수행할 수 있다. 반복은 수행하는 작업이 완료될 때 까지 계속 반복 루프 (for, while 구조) 재귀는 주어진 문제의 해를 구하기 위해 동일하면서 더 작은 문제의 해를 이용하는 방법 하나의 큰 문제를 해결할 수 있는 (해결하기 쉬운) 더 작은 문제로 쪼개고 결과들을 결합한다. 반복 구조 초기화 반복되는 명령문을 실행하기 전에 조건 검사에 사용할 변수의 초기 값 설정 조건 검사 반복할 명령문 실행 업데이트 무한 루프가 되지 않게 조건이 거짓이 되게 한다. 재귀적 알고리즘 재귀적 정의는 두 부분으로 나뉜다. 하나 또는 그 이상의 기본 경우 (basis case or rule) 집합에 포함되어 있는 원소로 induction을 생성하기 위한 시드(seed) 역할 하나 또는 그 이상의 유도된 경우 (inductive case or rule) 새로운 집합의 원소를 생성하기 위해

0.1 순열, 부분집합, 조합 [내부링크]

algorithm day10 순열, 부분집합, 조합 0.1.1 순열 개념 서로 다른 것들 중 몇 개를 뽑아서 한 줄로 나열하는 것 서로 다른 n 개 중 r 개를 택하는 순열 nPr = n * (n-1) * (n-2) * (n-3) * ...*(n-r+1) nPn = n!이라고 표기 다수의 알고리즘 문제들은 순서화된 요소들의 집합에서 최선의 방법을 찾는 것과 관련 있다. ex) TSP (Traveling Salesman Problem) N 개의 요소들에 대해서 n! 개의 순열들이 존재한다. 재귀를 이용한 순열 생성 # 자리를 고정하는 순열 def f(i,k, r): if i == r: print(p) else: for j in range(k): if not used[j]: # a[j]가 아직 사용되지 않았으면 used[j] = 1 # a[j] 사용됨으로 표시 p[i] = a[j] # p[i]는 a[j]로 결정 f(i+1,k,r) # p[i+1] 값을 결정하러 이동 used[j] = 0

0.1 탐욕 알고리즘, 활동 선택 [내부링크]

algorithm day10 탐욕 알고리즘, 활동 선택 0.1.1 탐욕 알고리즘 개념 최적 해를 구하는 데 사용되는 근시안적인 방법 일반적으로, 머릿속에 떠오르는 생각을 검증 없이 바로 구현 여러 경우 중 하나를 선택 할 때마다 그 순간에 최적이라고 생각되는 것을 선택해 나가는 방식으로 진행하여 최종적인 해답에 도달 각 선택 시점에서 이루어지는 결정은 지역적으로는 최적이지만, 그 선택들을 계속 수집하여 최종적인 해답을 만들었다고 하여, 그것이 최적이라는 보장이 없다. 한번 선택된 것은 번복하지 않는다. 그래서 제한적인 문제들에 적용된다. 동작 과정 해 선택 : 현재 상태에서 부분 문제의 최적 해를 구한 뒤, 이를 부분 해 집합에 추가 실행 가능성 검사 : 새로운 부분 해 집합이 실행 가능한 지를 확인 -> 문제의 제약 조건을 위반하지 않는 지를 검사 해 검사 : 새로운 부분 해 집합이 문제의 해가 되는지를 확인. 아직 전체 문제의 해가 완성되지 않았다면 1의 해 선택부터 다시 시작

21일은 너무 힘들어 [내부링크]

2022년 9월 25일 24일 토요일, 유독 오랫동안 잠에 들었던 날이었다. 해가 높아진 시간에 깨어나 간단하게 할 일을 하니 4시가 조금 넘었다. 원래는 여자친구를 10월 초에 만나기로 했었다. 하지만 벌써 2주째 보지 못해 늦은 시간이었지만 5시 기차를 타고 한걸음에 달려갔다. 평소보다 짧은 5시간 정도의 만남이지만 너무 알차고 행복한 하루를 보내 기분이 좋았다. 앞으로는 2주에 한번 꼭 봐야겠다! PM 9:10

SWEA-최대 상금 [내부링크]

# 주어진 숫자판들 중 2개를 선택해 정해진 횟수만큼 자리를 교환 # 왼쪽부터 10^N 자리 # 주어진 횟수만큼 교환이 이루어져야하고 동일한 위치의 교환이 가능 # 수를 계산하는 함수 # cnt : 몇 번 바꿨는지 보는 변수 def solve(cnt): global maxV if cnt == change: result = ''.join(numbers) if maxV < int(result): maxV = int(result) return # change번 교환을 해야한다. # 자리를 바꾸고 그 다음 자리부터 다시 바꿔야한다. # 자리를 바꾼 값을 check해서 중복된 값이 없도록 한다. else: for i in range(N): for j in range(i+1,N): numbers[i], numbers[j] = numbers[j], numbers[i] char = ''.join(numbers) if char not in check[cnt]: check[cnt].append(cha

0.1 분할 정복 & 백트래킹 [내부링크]

algorithm day11 분할 정복 & 백트래킹 0.1.1 분할 정복 설계 전략 분할 : 해결할 문제를 여러 개의 작은 부분으로 나눈다. 정복 : 나눈 작은 문제를 각각 해결한다. 통합 : 해결된 해답을 모은다. 분할 정복 기반의 알고리즘 # 거듭제곱 : O(logn) def recursive_power(x,n): if n == 1: return x if not n%2: # 짝수 y = recursive_power(x,n/2) return y*y else: # 홀수 y = recursive_power(x,(n-1)/2) 병합 정렬 여러 개의 정렬된 자료의 집합을 병합하여 한 개의 정렬된 집합으로 만드는 방식 외부 정렬의 기본이 되는 알고리즘 시간 복잡도 : O(nlogn) 과정 전체 자료 집합에 대해 최소 크기의 부분 집합이 될 때까지 분할 작업을 계속한다. 2 개의 부분 집합을 정렬하면서 하나의 집합으로 병합 알고리즘 # 분할 과정 # m : list def merge_sort

SWEA-병합 정렬 [내부링크]

# 병합 과정에서 왼쪽 마지막 원소가 오른쪽 마지막 원소보다 크면 출력 # 병합 정렬 def merge_sort(arr): global cnt if len(arr) < 2: return arr mid = len(arr) // 2 low_arr = merge_sort(arr[:mid]) high_arr = merge_sort(arr[mid:]) # 병합과정에서 맨 뒷자리를 비교 if low_arr[-1] > high_arr[-1]: cnt += 1 merged_arr = [] l = h = 0 while l < len(low_arr) and h < len(high_arr): if low_arr[l] < high_arr[h]: merged_arr.append(low_arr[l]) l += 1 else: merged_arr.append(high_arr[h]) h += 1 merged_arr += low_arr[l:] merged_arr += high_arr[h:] return merged

시디즈 T20 사용 후기 [내부링크]

2022년 10월 01일 의자를 받고 일주일 정도 사용해 본 후기를 남기려고 한다. 처음 의자를 받았을 때 조립이 안된 상태로 와서 혼자 조립을 했다. 조립 자체는 설명서를 보고 누구나 할 수 있어 생각보다 재미있는 경험이었다. 조립을 다 한 뒤 의자에 앉았을 때 신세계를 경험했다. 원래 사용하던 의자는 쿠션감이 약해 오래 앉기가 힘들었고 오래 앉아 있으면 허리 부분이 너무 아팠다. 하지만 시디즈 의자는 안정적으로 허리를 잡아주고 쿠션감도 너무 편해서 오래 앉아 있어도 피로감이 생기지 않아 너무 좋았다. 누군가에게 충분히 추천해 줄 수 있고 돈이 전혀 아깝지 않았다.

0.1 그래프(BFS, DFS) [내부링크]

algorithm day12 그래프(BFS, DFS) 0.1.1 그래프 기본 개념 그래프는 아이템들과 이들 사이의 연결 관계를 표현한다. 그래프는 정점들의 집합과 이들을 연결하는 간선들의 집합으로 구성된 자료 구조 IVI : 정점의 개수 IEI : 그래프에 포함된 간선의 개수 최대 간선 수 : IVI(IVI-1)/2 개 선형 자료 구조나 트리 자료 구조로 표현하기 어려운 N:N 관계를 가지는 원소들을 표현하기에 용이 그래프의 유형 무향 그래프 방향(화살표)이 없는 그래프 유향 그래프 방향(화살표)이 있는 그래프 가중치 그래프 방향에 따라 가중치가 있는 그래프 사이클 없는 방향 그래프 완전 그래프 정점들에 대해 가능한 모든 간선들을 가진 그래프 부분 그래프 원래 그래프에서 일부의 정점이나 간선을 제외한 그래프 인접 두 개의 정점에 간선이 존재하면 서로 인접해 있다고 한다. 완전 그래프에 속한 임의의 두 정점들은 모두 인접해 있다. 그래프 경로 경로 : 간선들을 순서대로 나열한 것 단순

0.2 그래프(서로소 집합, MST, 최단 경로) [내부링크]

algorithm day12 그래프(서로소 집합, MST, 최단 경로) 0.2.1 서로소 집합들 개념 서로소 or 상호 배타 집합들은 서로 중복 포함된 원소가 없는 집합들 즉, 교집합이 없다. 집합에 속한 하나의 특정 멤버를 통해 각 집합들을 구분, 이를 대표자라 한다. 표현하는 방법 연결 리스트 트리 상호 배타 집합 연산 Make-Set(x) Find-Set(x) Union(x,y) 연결 리스트 같은 집합의 원소들은 하나의 연결 리스트로 관리 연결 리스트의 맨 앞의 원소를 집합의 대표 원소로 삼는다. 각 원소는 집합의 대표 원소를 가리키는 링크를 갖는다. 트리 하나의 집합을 하나의 트리로 표현 자식 노드가 부모 노드를 가리키며 루트 노드가 대표자가 된다. Make-Set(x) 유일한 멤버 x를 포함하는 새로운 집합을 생성하는 연산 def make_set(x): p[x] = x Find-Set(x) x를 포함하는 집합을 찾는 연산 # 재귀를 이용한 방법 def find_set(x):

SWEA-동철이의 일 분배 [내부링크]

# 직원 번호 : 1~N # 일 번호 : 1~N # i번 직원이 j번 일을 하면 성공 확률이 Pij # 주어진 일이 모두 성공할 확률의 최댓값 def solve(j,v): global maxV if j == N and maxV < v: maxV = v if v == 0: return if v < maxV: return for i in range(N): if not visited[i]: visited[i] = 1 solve(j+1,v*Pij[i][j]/100) visited[i] = 0 T = int(input()) for tc in range(1,T+1): N = int(input()) Pij = [list(map(int,input().split())) for _ in range(N)] visited = [0]*N maxV = 0 solve(0,1) print(f'#{tc} {maxV * 100:.6f}')

SWEA-이진 탐색 [내부링크]

# 정수 N개가 정렬한 상태로 리스트 A에 저장 # B에 저장된 M개의 정수가 A에 들어있는 수 인지 이진 탐색으로 확인 def search(N_lst,l,r,key,v): global cnt if l > r: return v else: middle = (r+l) // 2 if key == N_lst[middle]: cnt += 1 return if key < N_lst[middle]: return search(N_lst,l,middle-1,key,v+'1') elif key > N_lst[middle]: return search(N_lst,middle+1,r,key,v+'0') # 첫 줄에 테스트케이스 T T = int(input()) for tc in range(1,T+1): N, M = map(int,input().split()) N_lst = list(map(int,input().split())) M_lst = list(map(int,input().split())) l = 0

SWEA-전기 버스2 [내부링크]

# 충전지마다 최대로 운행할 수 있는 정류장 수가 있다. # 마지막 정류장에는 배터리가 없다. # 테스트 케이스 T T = int(input()) for tc in range(1,T+1): # 정류장 수 N, 정류 별 배터리 Mi N, *Mi = map(int,input().split()) ride = [0]*(N-1) for i in range(N-1): ride[i] = Mi[i]+i start = 0 cnt = 0 while start < N-1: maxV = 0 if ride[start] >=N-1: break for i in range(start,ride[start]+1): if maxV <= ride[i]: maxV = ride[i] start = i cnt += 1 print(f'#{tc} {cnt}')

SWEA-최소 생산 비용 [내부링크]

# 최소 생산 비용을 구하라 # 한 공장에서는 하나의 제품만 생성 def choice(num, v): global minV if v > minV: return if num == N and minV > v: minV = v return for i in range(N): if not visited[i]: visited[i] = 1 choice(num+1,v+Vij[num][i]) visited[i] = 0 # 테스트 케이스 T = int(input()) for tc in range(1, T + 1): # 제품 수 N N = int(input()) # 생산 비용 Vij Vij = [list(map(int, input().split())) for _ in range(N)] visited = [0]*N minV = 9999 choice(0, 0) print(f'#{tc} {minV}')

SWEA-퀵 정렬 [내부링크]

# 퀵 정렬을 수행하는 함수 def partition(l,r): pivot = ai[l] i, j = l, r while i <= j: while i <= j and ai[i] <= pivot: i += 1 while i <= j and ai[j] > pivot: j -= 1 if i < j: ai[i],ai[j] = ai[j], ai[i] ai[l],ai[j] = ai[j], ai[l] return j def quick_sort(l,r): if l < r: p_idx = partition(l,r) quick_sort(l,p_idx-1) quick_sort(p_idx+1,r) # 첫 줄에 테스트케이스 T T = int(input()) for tc in range(1,T+1): N = int(input()) # N개의 정수 ai ai = list(map(int,input().split())) quick_sort(0,N-1) print(f'#{tc} {ai[N // 2]}')

SWEA-연산 [내부링크]

# 자연수 N에 몇 번의 연산을 통해 M을 만들 수 있는가 # 사용할 수 있는 연산 +1, -1, *2, -10 def bfs(N, M): while queue: # 큐에서 하나씩 꺼내 목표 값이랑 같은지 비교 queue.pop(0) if queue[0][0] == M: result = queue[0][1] break # 다르면 다시 큐의 값을 계산하여 큐의 뒤에 삽입 # 이것을 반복하면서 계속 값을 비교 for i in queue: for j in numbers: if j == 2 and i[0] * j > 0 and i[0] * j <= M + 1 and not visited[i[0] * j]: visited[i[0] * j] = 1 queue.append([i[0] * j, i[1] + 1]) else: if i[0] + j > 0 and i[0] + j <= M + 1 and not visited[i[0] + j]: visited[i[0] + j] = 1 queue.appen

SWEA-그룹 나누기 [내부링크]

# 번호에 적힌 숫자는 같은 조 def find_set(x): while x != p[x]: x = p[x] return x def union(x,y): p[find_set(y)] = find_set(x) # 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1,T+1): N, M = map(int,input().split()) # M 쌍의 번호 num = list(map(int,input().split())) p=[_ for _ in range(N+1)] for i in range(M): union(num[2*i],num[2*i+1]) result = [] for i in range(1,N+1): if find_set(i) in result: pass else: result.append(find_set(i)) print(f'#{tc} {len(result)}')

SWEA-최소 비용 [내부링크]

# (0,0)에서 (N-1,N-1)까지 갈 때 최소 비용을 구함 # 높이가 1 증가할 때 비용도 1 증가 def bfs(r,c): visited[r][c] = 0 dr = [0,1,0,-1] dc = [1,0,-1,0] queue.append((r,c)) while queue: x, y = queue.pop(0) for i in range(4): nr = x + dr[i] nc = y + dc[i] if 0<= nr < N and 0<= nc < N: height = 0 if H[nr][nc] - H[x][y] > 0: height = H[nr][nc] - H[x][y] if visited[nr][nc] > visited[x][y] + 1 + height: visited[nr][nc] = visited[x][y] + 1 + height queue.append((nr,nc)) return visited[N-1][N-1] # 첫 줄에 테스트 케이스 T = int(input()) for

SWEA-최소 신장 트리 [내부링크]

# 최소 신장 트리를 구성 # 최소 신장 트리를 구성하는 간선을 모두 더해 출력하는 프로그햄 def prim(r,V): MST = [0]*(V+1) MST[r] = 1 s = 0 for _ in range(V): u = 0 minV = 10000 for i in range(V+1): if MST[i] == 1: for j in range(V+1): if adj[i][j] > 0 and MST[j] == 0 and minV>adj[i][j]: u = j minV = adj[i][j] s += minV MST[u] = 1 return s # 첫 줄에 테스트 케이스 T = int(input()) for tc in range(1,T+1): # 마지막 노드 번호 V, 간선의 개수 E V, E = map(int,input().split()) # 처음 가중치를 최댓값으로 초기화한다. adj = [[0]*(V+1) for _ in range(V+1)] for i in range(E): n1,n2,

SWEA-최소 이동 거리 [내부링크]

# E개의 일방통행 구간 # 0~N번 # 0~N 지점까지 최소한의 거리 def dijkstra(start): distance = adj[start][:] visited = [0]*(N+1) visited[start] = 1 distance[start] = 0 while sum(visited) <= N: min_idx = 0 min_val = 0xffffff for i in range(N+1): if not visited[i] and distance[i] < min_val: min_idx = i min_val = distance[i] visited[min_idx] = 1 for i in range(N+1): if not visited[i] and distance[i] > min_val + adj[min_idx][i]: distance[i] = min_val + adj[min_idx][i] return distance # 첫 줄에 테스트 케이스 T = int(input()) for tc

SWEA-보급로 [내부링크]

# deque를 활용한 풀이 from collections import deque def bfs(r,c): dr = [0,1,0,-1] dc = [1,0,-1,0] visited[r][c] = 0 queue.append((r,c)) while queue: x, y = queue.popleft() for i in range(4): nr = x + dr[i] nc = y + dc[i] if 0<= nr < N and 0<= nc < N: if visited[nr][nc] > data[nr][nc] + visited[x][y]: visited[nr][nc] = data[nr][nc] + visited[x][y] queue.append((nr,nc)) return visited[N-1][N-1] T = int(input()) for tc in range(1,T+1): N = int(input()) data = [list(map(int,input())) for _ in range(N)] vi

SWEA-수영장 [내부링크]

# bfs를 이용한 방법 def dfs(n): global sum if n == 12: result.append(sum) return for i in range(3): if i == 0: sum += schedule[n]*day dfs(n+1) sum -= schedule[n]*day elif i == 1: sum += month dfs(n+1) sum -= month elif i == 2 and n <= 9: sum += t_month dfs(n+3) sum -= t_month T = int(input()) for tc in range(1,T+1): day,month,t_month,year = map(int,input().split()) schedule = list(map(int,input().split())) result = [year] sum = 0 dfs(0) print(f'#{tc} {min(result)}') # DP를 이용한 방법 T=int(input()) for tc

SWEA-요리사 [내부링크]

# N개의 식재료가 있다. # N/2개씩 나누어 두 개의 요리를 한다. # A음식과 B음식 맛의 차이가 최소가 되도록 재료를 배분 # 식재로 i,j는 시너지 Sij가 발생 # 음식의 맛은 시너지들의 합 # 식재료의 수 N은 4이상 16이하의 짝수 # 시너지 Sij는 1이상 20000이하의 정수 def nCr(n, ans, r): if n == len(arr): if len(ans) == r: temp = [i for i in ans] A = 0 # 조합을 구해서 그 값을 comb배열에 저장 for i in range(len(temp)): for j in range(i,len(temp)): A += Sij[temp[i]][temp[j]] + Sij[temp[j]][temp[i]] comb.append(A) return ans.append(arr[n]) nCr(n + 1, ans, r) ans.pop() nCr(n + 1, ans, r) # 테스트 케이스 T T = int(input()

SWEA-하나로 [내부링크]

# 모든 섬을 해저터널로 연결 # 환경 부담금 = E(환경 부담 세율) * L(각 해저터널 길이)^2 # 환경 부담금을 최소로 하며 모든 섬을 연결, 길이를 최소 def prim(s): MST = [0xfffffffffffffffff]*N check = [0]*N MST[s] = 0 check[s] = 1 for i in range(N): MST[i] = ((rocate[s][0] - rocate[i][0])**2 + (rocate[s][1] - rocate[i][1])**2) while sum(check) < N: min_val = 0xffffffffffffffff min_idx = 0 for i in range(N): if not check[i] and min_val > MST[i]: min_val = MST[i] min_idx = i check[min_idx] = 1 for i in range(N): if not check[i]: value = ((rocate[min_idx][

1. 컴퓨터 구조 개론 및 조합 회로 [내부링크]

※KOCW-컴퓨터 구조 및 실습 (목포대학교, 안동순 교수)를 참고하여 정리했습니다.※ Computer Digital Logic Circuit 노이만 구조 컴퓨터 2 진수로 동작 내부 구조 Input device (입력 장치) Output device (출력 장치) CPU memory device (기억 장치) 전부 input과 output을 가지고 있고 wire(bus)로 연결되어 있다. 동작 OS OS(program)로 동작한다. OS가 전기를 0인지 1인지 인식한다. clock clock은 직류 전압과 같은 형태로 나타난다. 전기를 켜고 끄면서 0과 1의 logical을 생성한다. clock의 빠르기로 컴퓨터의 성능이 결정된다. clock의 주파수(f=1/T)가 높아지면 시간은 짧아지고 속도가 증가한다. wire(bus) 종류 address bus data bus control bus 통신(이동)을 담당한다. 화살표로 통신의 방향을 나타낸다. <-> : 양방향 <- : 단방향

1. Database, SQL의 개념 [내부링크]

1. Database 개요 파일을 이용한 데이터 관리 장점 운영체제에 관계 없이 어디에서나 쉽게 사용이 가능하다. email이나 메신저를 이용해 간편하게 전송이 가능하다. 단점 성능과 보안적 측면에서 한계가 명확하다. 대용량 데이터를 다루기에 적합하지 않다. 데이터를 구조적으로 정리하기에 어려움이 있다. 확장이 불가능한 구조이다. 스프레드 시트를 이용한 데이터 관리 스프레드 시트 (엑셀 시트)을 사용 스프레드 시트는 컬럼(열)을 통해 데이터의 유형을 지정하고 레코드(행)을 통해 구체적인 데이터 값을 포함한다. 데이터베이스를 이용한 데이터 관리 스프레드 시트와 달리 프로그래밍 언어를 사용해 작동 시킬 수 있다. 가장 많이 쓰이는 유형은 RDB (Relational Database)라고 부르는 관계형 데이터베이스 RDB는 각각의 데이터를 테이블에 기입한다. Database 정의 체계화된 데이터의 모임 여러 사람이 공유하고 사용할 목적으로 통합 관리되는 정보의 집합 검색, 구조화 같은 작

2. DDL (Data Definition Language) [내부링크]

사전 준비 bash 터미널에서 'mkdir 파일명' 을 통해 폴더를 생성 'cd 파일명'을 하여 폴더로 이동 code~/.bashrc를 입력하여 .bashrc라는 파일 에디터창을 vscode로 오픈 .bashrc 내부에 alias sqlite3="winpty sqlite3"을 입력하고 저장 vscode 터미널을 열어 source~/.bashrc를 실행 데이터베이스 파일 생성 'sqlite3 파일명.sqlite3' 을 입력하여 데이터베이스를 생성 이미 파일이 존재한다면 동일한 명령어를 입력하여 실행 .mode column을 실행하여 컬럼 별로 볼 수 있게 설정 .header on을 실행하여 칼럼명을 같이 확인할 수 있게 설정 DDL.sql 파일 생성 DDL.sql 화면에서 마우스 우측 버튼을 눌러 Use Database 선택 데이터베이스 목록에서 생성한 파일 선택 Create Table 데이터베이스에 새 테이블을 만든다. Query 실행하기 실행하고자 하는 명령문에 커서를 두고 마우스

특별한 생일 축하 [내부링크]

2022년 10월 09일 10월의 생일을 맞이해서 여자친구와 흑백 사진을 찍었다. 사진관에서 찍는 것은 처음이라 포즈도 어색하고 서툴렀지만 셀프 사진관이라 큰 부담이 없었다. 사진을 20분간 찍은 다음 찍힌 사진들을 보니 생각보다 잘 나온 사진이 많아서 고르기가 힘들었다. 그중 몇 개를 밑에 올렸다. 여자친구가 생일 선물로 가방과 이때까지 핸드폰으로 찍은 사진을 인화해서 주었다. 가방도 너무 좋았지만 인화된 사진을 보니 핸드폰으로 보는 것과 느낌이 많이 달라서 너무 이쁘고 보면서 추억이 많이 떠올라 의미 있는 선물이었다. 평생 못 잊을 선물은 준 뭉지에게 너무 고마웠고 많이 사랑한다고 전해주고 싶다.

0.1 데이터베이스 관계 (N : 1) [내부링크]

0.1.1 A many-to-one relationship RDB에서 관계 1 : 1 one-to-one relationships 한 테이블의 레코드 하나가 다른 테이블의 레코드 단 한 개와 관련된 경우 N : 1 Many-to-one relationships 한 테이블의 0 개 이상의 레코드가 다른 테이블의 레코드 한 개와 관련된 경우 기준 테이블에 따라 (1 : N, one-to-many relationships) 라고 한다. N : N Many-to-many relationships 한 테이블의 0 개 이상의 레코드가 다른 테이블의 0 개 이상의 레코드와 관련된 경우 양쪽 모두에서 N : 1 관계를 가진다. Foreign Key 개념 외래 키 (외부 키) 관계형 데이터베이스에서 한 테이블의 필드 중 다른 테이블의 행을 식별할 수 있는 키 참조하는 테이블에서 1 개의 키에 해당, 이는 참조되는 측 테이블의 기본 키(Primary Key)를 가리킨다. 참조하는 테이블의 행 1 개의

0.2 데이터베이스 관계 (N : 1) [내부링크]

0.2.1 N : 1 (Article - User) Referencing the User model settings.AUTH_USER_MODEL 반환 값 : 'accounts.User' (문자열) User 모델에 대한 외래 키 또는 N : N 관계를 정의 할 때 사용 models.py의 모델 필드에서 User 모델을 참조할 때 사용 get_user_model() 반환 값 : User Object (객체) 현재 활성화(active)된 User 모델을 반환 customizing한 User 모델이 있을 경우는 Custom User 모델, 그렇지 않으면 User를 반환 models.py가 아닌 다른 모든 곳에서 User model을 참조할 때 사용 모델 관계 설정 Article 모델에 User 모델을 참조하는 외래 키 작성 Migration 진행 모든 칼럼은 NOT NULL 제약 조건이 있기 때문에 데이터가 없이는 새로 추가되는 외래 키 필드 user_id가 생성되지 않는다. 그래서 기본

Project - 영화 기반의 사이트 (게시글-메인) [내부링크]

1. Main page 메인 화면 현재 사이트의 메인 페이지는, 데이터베이스에 저장한 모든 영화 정보를 보여준다. 데이터베이스에는 영화의 제목, 줄거리, 장르, 평점, 관객 수, 개봉일, 포스터url이 들어간다. 스켈레톤 코드 모든 HTML 파일은 스켈레톤 코드를 기반으로 작성 되었다. 스켈레톤 코드는 메인 페이지에서 보이는 네비게이션 바를 만드는 코드이다. 네비게이션 바의 우측 햄버거 버튼을 누르면 나오는 부분 # 메인 페이지에서 맨 위의 네비게이션 바를 나타낸다. <nav class="navbar bg-light fixed-top"> <div class="container-fluid"> <div class="d-flex justify-content-row"> # 맨 왼쪽 아이콘을 누르면 메인 페이지로 이동한다. <a class="navbar-brand" href="{% url 'movies:index' %}">Movies</a> # 검색 기능을 담당하는 코드이지만 작동이 되지는

Project - 영화 기반의 사이트 (게시글-생성) [내부링크]

2. 생성 페이지 입력을 받아 게시글을 생성하는 페이지 게시글 생성 페이지는, 사용자의 입력을 받아 데이터베이스에 저장하는 역할을 한다. modelform을 활용해 입력을 데이터베이스에 저장하고 bootstrap을 이용해 꾸몄다. 게시글 생성 코드 modelform을 이용해 입력받은 데이터를 데이터베이스에 저장한다. {% extends 'base.html' %} {% block content %} <div class="mx-auto my-3" style="width: 650px;"> <hr> <br> <br> <hr style="width: 550px;"> # modelform을 이용해서 입력을 데이터베이스에 저장하는 코드 <form action="{% url 'movies:create' %}" method="POST"> {% csrf_token %} <ul class="list-group list-group-horizontal"> <li class="list-group-item l

Project - 영화 기반의 사이트 (게시글-detail) [내부링크]

3. 세부사항 페이지 내가 쓴 게시글이 아닌 글에 들어갔을 때 나오는 화면 내가 쓴 글에 들어갔을 때 나오는 화면 영화 정보 세부 페이지는, 데이터베이스에 저장된 이 영화의 정보를 더 자세히 볼 수 있다. RDB를 구성해서 세부 페이지에 댓글을 달 수 있게 만들었다. 내가 작성한 글만 수정과 삭제가 가능하고 댓글 또한 내가 쓴 것만 삭제가 가능하다. 디테일 코드 데이터베이스에 저장된 데이터를 불러와 원하는 방식으로 표현하였다. RDB를 구현하여 로그인 된 사용자는 댓글을 쓸 수 있고 삭제할 수도 있다. 게시글을 쓴 사람이 아니면 게시글을 수정하거나 삭제할 수 없다. {% extends 'base.html' %} {% block content %} <div class="mx-auto" style="width: 900px; height: auto;"> <br> <br> <br> # 생성 때 받은 포스터url을 이용해 포스터를 가운데에 표현한다. <div class="d-flex just

Project - 영화 기반의 사이트 (게시글-수정) [내부링크]

4. 수정 페이지 수정하는 페이지 수정하는 페이지는, 처음 게시글을 생성할 때 적은 정보가 모두 들어가있다. 내가 원하는 것을 수정한 뒤 수정하기 버튼을 누르면 수정된 정보가 데이터베이스에 저장된다. 수정 코드 데이터베이스에 저장된 정보를 그대로 불러와 내가 원하는 부분을 수정한 뒤 수정된 정보를 다시 데이터베이스에 저장하는 코드. {% extends 'base.html' %} {% block content %} <div class="mx-auto my-3" style="width: 650px;"> <br> <br> <br> # 데이터베이스에 저장된 정보를 불러와 수정한 뒤 수정한 데이터를 저장한다. <form action="{% url 'movies:update' movie.pk%}" method="POST"> {% csrf_token %} <ul class="list-group list-group-horizontal"> <li class="list-group-item list-g

Project - 영화 기반의 사이트 (게시글-내가 쓴 게시글만 보는 페이지) [내부링크]

5. 내가 쓴 게시글을 보는 페이지 내가 쓴 게시글을 보는 페이지 네비게이션 바에서 이동 내가 쓴 게시글을 보는 페이지는, 사용자가 게시글을 작성하면 사용자의 key값을 게시글 데이터베이스에 같이 저장하였고 이 값을 이용해 내가 쓴 게시글만 보여줄 수 있는 페이지를 구성하였다. 내가 작성한 게시글 코드 모든 HTML 파일은 스켈레톤 코드를 기반으로 작성 되었다. 스켈레톤 코드는 메인 페이지에서 보이는 네비게이션 바를 만드는 코드이다. {% extends 'base.html' %} {% block content %} <br> <hr> <br> # 모든 게시글 중에서 내가 쓴 게시글을 if문을 이용해 판단한다. {% for movie in movies %} {% if movie.user == user %} <div class="d-flex position-relative border border-1 rounded-2"> <img src="{{ movie.poster_url }}" cla

Project - 영화 기반의 사이트 (게시글-기타) [내부링크]

6. 기타 기능들 게시글 삭제 views 코드 게시글을 쓴 사용자만 게시글을 삭제할 수 있게 했다. # 단일 영화 데이터 삭제 및 index로 보냄 # POST @login_required def delete(request,pk): movie = Movie.objects.get(pk=pk) if request.method=="POST": # 유효성 검사 후 삭제 if request.user.is_authenticated: if request.user == movie.user: movie.delete() 댓글 삭제 views 코드 댓글을 쓴 사용자만 삭제할 수 있도록 했다. # 댓글 삭제 @login_required def comment_delete(request,movie_pk,comment_pk): comment = Comment.objects.get(pk=comment_pk) # 유효성 검사 후 삭제 if request.user.is_authenticated: if request

Project - 영화 기반의 사이트 (인증-로그인) [내부링크]

1. 로그인 페이지 로그인 화면 로그인 페이지는, django내부에 있는 form을 이용하였다. 로그인 코드 django의 form을 이용하였으며 버튼 모양은 bootstrap을 이용해 꾸몄다. {% extends 'base.html' %} {% block content %} <br> <hr> <br> <form action="{% url 'accounts:login' %}" method="POST"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="로그인" class="btn btn-warning"> <a href="{% url 'accounts:signup' %}" class="btn btn-success">회원가입</a> </form> {% endblock content %} 로그인 views코드 django 내부에 AuthenticationForm을 이용하여 로그인 형식을 만들었다. from django.contri

Project - 영화 기반의 사이트 (인증-회원 가입) [내부링크]

2. 회원가입 페이지 회원가입 페이지 회원가입 페이지는, django 내부의 form을 통해 회원가입을 진행할 수 있다. user를 변경한 경우 UserCreationForm을 변경해주어야 한다. 회원가입 코드 django 내부의 form을 통해 회원가입을 진행한다. {% extends 'base.html' %} {% block content %} <br> <hr> <br> <form action="{% url 'accounts:signup' %}" method="POST"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="회원가입" class="btn btn-warning"> <a href="{% url 'accounts:login' %}" class="btn btn-danger">돌아가기</a> </form> {% endblock content %} 회원가입 views 코드 회원가입 form인 UserCreationFo

Project - 영화 기반의 사이트 (인증-회원 정보 수정) [내부링크]

3. 회원 정보 수정 페이지 회원 정보 수정 페이지 회원 정보 수정 페이지는, 게시글 수정과 비슷한 원리이다. 데이터베이스에 저장된 정보를 그대로 불러와 사용자에게 보여준 후 사용자가 변경한 데이터를 다시 저장한다. 회원 정보 수정 코드 django가 제공하는 회원 정보 수정 form을 이용하였다. {% extends 'base.html' %} {% block content %} <br> <hr> <br> <form action="{% url 'accounts:update_signup' %}" method="POST"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="수정하기" class="btn btn-warning"> <a href="{% url 'movies:index'%}" class="btn btn-danger">돌아가기</a> </form> {% endblock content %} 회원 정보 수정 views코드

Project - 영화 기반의 사이트 (인증-비밀번호 변경) [내부링크]

4. 비밀번호 변경 페이지 비밀번호 변경 페이지 비밀번호 변경 페이지는, django 내부에서 제공하는 비밀번호 변경 form을 이용하였다. 비밀번호 변경 코드 django 내부에 비밀번호 변경 form을 이용하였다. {% extends 'base.html' %} {% block content %} <br> <hr> <br> <form action="{% url 'accounts:password' %}" method="POST"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="변경하기" class="btn btn-warning"> <a href="{% url 'movies:index'%}" class="btn btn-danger">돌아가기</a> </form> {% endblock content %} 비밀번호 변경 views 코드 django 내부에 비밀번호 변경 form을 이용하였다. 회원 정보 수정과 마찬가지로 데이터

Project - 영화 기반의 사이트 (인증-기타) [내부링크]

5. 로그아웃, 회원 탈퇴 로그아웃 코드 django 내부에 로그아웃 함수를 이용하였다. from django.contrib.auth import logout as custom_logout # 로그아웃 @login_required def logout(request): if request.user.is_authenticated: custom_logout(request) return redirect('movies:index') 회원 탈퇴 코드 현재 user를 데이터베이스에서 삭제한 뒤 로그아웃하는 코드로 구현하였다. # 회원탈퇴 @login_required def delete(request): if request.user.is_authenticated: request.user.delete() custom_logout(request) return redirect('movies:index')

단계별로 풀어보기 - python ( 9 단계) [내부링크]

10814번 # 나이가 증가하는 순으로 나이가 같으면 먼저 가입한 사람이 # 앞에 온다. import sys N = int(sys.stdin.readline()) # 나이를 인덱스로 받아 저장하는 리스트 data = [[] for _ in range(201)] for i in range(N): age, name = input().split() data[int(age)].append([age, name]) # 입력 받은 데이터를 출력 for i in data: for j in i: print(*j) 1181번 import sys # 알파벳 소문자로 이루어진 N개의 단어를 정렬 # 1. 길이가 짧은 것부터 # 2. 길이가 같으면 사전 순으로 N = int(sys.stdin.readline()) # 문자열의 최대 길이가 50이라 50번까지 리스트를 만듬 words = [[] for _ in range(51)] for i in range(N): word = sys.stdin.readline

단계별로 풀어보기 - python ( 9 단계) [내부링크]

2751번 #N개의 수가 주어졌을 때, 오름차순으로 정렬하는 프로그램 import sys # 첫째 줄에 수의 개수 N N = int(sys.stdin.readline()) array = [int(sys.stdin.readline()) for _ in range(N)] array.sort() for i in array: print(i) 10989번 import sys input = sys.stdin.readline n = int(input()) num = [0]*10001 for i in range(n): num[int(input())] +=1 for i in range(10001): #for i in ragne(1, 10001)로 했을 때 통과 if(num[i]!=0): for j in range(num[i]): print(i) 18870번 import sys # 좌표가 주어지고 # 주어진 좌표 중 현재 좌표보다 작은 좌표의 개수가 압축 좌표가 된다. N = int(sys.stdin

단계별로 풀어보기 - python ( 9 단계) [내부링크]

11651번 import sys # 2차원 평면 위의 점 N개 # x좌표를 증가하는 순으로, y좌표가 같으면 s좌며가 증가하는 순으로 정렬 # 점의 개수 N(1이상 100000이하) N = int(sys.stdin.readline().strip('\n')) # +x좌표 리스트에 y좌표를 저장하는 빈 리스트 data_plus = [[] for _ in range(100001)] # -x좌표 리스트에 y좌표를 저장하는 빈 리스트 data_minus = [[] for _ in range(100001)] # i번 점의 위치 xi와 yi for i in range(N): xi, yi = map(int,sys.stdin.readline().strip('\n').split()) if yi >= 0: data_plus[yi].append(xi) else: data_minus[-yi].append(xi) # y좌표가 (-) 값인 리스트부터 출력 for i in range(100000,-1,-1):

특별한 생일 [내부링크]

2022년 10월 15일 10월 13일은 내 생일이었다. 어릴 때는 생일이 특별한 날이라는 느낌이 강했는데 나이를 먹어가면서 이런 느낌이 조금 옅어져 이제는 다른 날과 다를 게 없다. 하지만 내 여자친구 덕분에 평범했던 생일이 조금 특별해졌다. 장거리인 우리는 주말에 만나 10월 9일에 여자친구가 미리 축하해 주었다. 여자친구랑 먹은 케이크와 추워서 옷 빌려줬는데 코디가 귀여운 사진 9일에 여자친구가 축하해 줘서 생일 당일인 목요일에는 만날 예정이 없었다. 하지만 여자친구가 서프라이즈로 와줘 같이 저녁도 먹고 드라이브도 갔다. 내 생일 당일 와준 여자친구와 집에서 먹은 생일 케이크 짧은 3시간에 만남이었지만 너무 행복하고 특별한 생일을 보냈다. 할 일이 있는 와중에 나를 위해 찾아온 여자친구가 너무 고마웠고 여자친구에게 잘해야겠다는 생각이 드는 생일날이었다.

0.1 Static / Media [내부링크]

Static / Media 0.1.1 Managing static files 개요 정적 파일 응답할 때 별도의 처리 없이 파일 내용을 그대로 보여주면 되는 파일 사용자의 요청에 따라 내용이 바뀌는 것이 아니라 요청한 것을 그대로 보여주는 파일 파일 자체가 고정되어 있고, 서비스 중에도 추가되거나 변경되지 않고 고정되어 있다. Django에서는 'static files'라고 한다. Django는 staticfiles 앱을 통해 정적 파일과 관련 된 기능을 제공한다. Media File 미디어 파일 사용자가 웹에서 업로드하는 정적 파일 유저가 업로드 한 모든 정적 파일 웹 서버와 정적 파일 웹 서버의 기본 동작 특정 위치 (URL)에 있는 자원을 요청 받고 응답 (HTTP response)을 처리하고 제공하는 것 웹 서버는 요청 받은 URL로 서버에 존재하는 정적 자원을 제공한다. Static files 구성 INSTALLED_APPS에 django.contrib.staticfiles가

0.2 Static / Media [내부링크]

Static / Media 0.2.1 Image Resizing 사전 준비 django-imagekit 모듈 설치 및 등록 썸네일 만들기 원본 이미지 저장 x 원본 이미지 저장 O 이미지가 출력되는 다른 detail 페이지에 이동 할 떄마다 썸네일이 생성된다. 0.2.2 QuerySet API Advanced .count() QuerySet과 일치하는 데이터베이스의 개체 수를 나타내는 정수를 반환 order_by() .order_by(*fields) QuerySet의 정렬을 재정의 기본적으로 오름차순으로 정렬, 필드명에 '-'(하이픈)을 작성하면 내림차순으로 정렬 인자로 '?'를 입력하면 랜덤으로 정렬 values() .values(*fields, **expressions) 모델 인스턴스가 아닌 딕셔너리 요소들을 가진 QuerySet을 반환 *fields는 선택인자이며 조회하고자 하는 필드명을 가변인자로 받는다. 필드를 지정하면 각 딕셔너리에는 지정한 필드에 대한 key와 value

0.1 데이터베이스 관계 (M:N) [내부링크]

데이터베이스 관계 (M:N) 0.1.1 Many to many relationship 개요 데이터 모델링 주어진 개념으로부터 논리적인 데이터 모델을 구성하는 작업 물리적인 데이터베이스 모델로 만들어 고객의 요구에 따라 특정 정보 시스템의 데이터베이스에 반영하는 작업 target model 관계 필드를 가지지 않는 모델 source model 관계 필드를 가진 모델 ManyToManyField ManyToManyField(to, **options) 다대다 (M:N) 관계 설정 시 사용하는 모델 필드 하나의 필수 위치인자가 필요하다. (M:N 관계로 설정할 모델 클래스) 모델 필드의 RelatedManager를 사용하여 관련 개체를 추가, 제거, 생성 등이 가능하다. add(), romove(), create(), clear()... 데이터베이스에서의 표현 Django는 다대다 관계를 나타내는 중개 테이블을 만든다. 테이블 이름은 ManyToManyField 이름과 이를 포함하는 모델의

0.2 데이터베이스 관계 (M:N) [내부링크]

데이터베이스 관계 (M:N) 0.2.1 M : N (User-User) Follow 구현하기 1. Profile 페이지 구현 2.Follow 구현 0.2.2 Fixtures Django에서는 fixtures를 사용해 앱에 초기 데이터를 제공할 수 있다 Providing data with fixtures fixtures Django가 데이터베이스로 가져오는 방법을 알고 있는 데이터 모음 fixtures 기본 경로 app_name/fixtures/ Django는 설치된 모든 app의 디렉토리에서 fixtures 폴더 이후의 경로로 fixtures 파일을 찾는다. fixtures 생성 및 로드 생성 (추출) dumpdata 응용 프로그램과 관련된 데이터베이스의 모든 데이터를 표줄 출력으로 출력 여러 모델을 하나의 json 파일로 만들 수 있다. manage.py와 동일한 위치에 data가 담긴 articles.json 파일이 생성된다. dumpdata의 출력 결과물은 loaddata의 입

여~~름, 갈, 겨~~울 [내부링크]

2022년 10월 22일 일교차가 심한 요즘 부쩍 가을이란 생각이 든다. 더운 날이 엊그제 같은데 갑자기 아침저녁으로 찬 바람이 내 몸을 어루만진다. 나무들도 점점 가을맞이를 준비하듯 옷을 갈아입고 있었다. 개인적으로 나무들이 다양한 색의 옷을 입고 있는 모습이 예쁘다고 생각한다. 다음 주에 여자친구랑 등산 가면서 아름다운 자연의 모습을 내 눈에 담고 와야겠다. PM 1:30

0.1 REST API [내부링크]

REST API 0.1.1 REST API HTTP Hyper Text Transfer Protocol HTML 문서와 같은 리소스 (resource, 자원)들을 가져올 수 있도록 하는 프로토콜(규칙, 약속) 웹상에서 콘텐츠를 전송하기 위한 약속 웹에서 이루어지는 모든 데이터 교환의 기초가 된다. '클라이언트-서버 프로토콜'이라고도 부른다. 클라이언트와 서버는 다음과 같은 개별적인 메시지 교환에 의해 통신한다. 요청(request) 클라이언트에 의해 전송되는 메시지 응답 (response) 서버에서 응답으로 전송되는 메시지 HTTP 특징 Stateless (무상태) 동일한 연결에서 연속적으로 수행되는 두 요청 사이에 링크가 없다. 즉, 응답을 마치고 연결을 끊는 순간 클라이언트와 서버 간의 통신이 끝나며 상태 정보가 유지되지 않는다. HTTP Request Methods 리소스에 대한 행위를 정의 리소스 HTTP 요청의 대상을 리소스(자원, 대상)이라고 한다. HTTP verbs라고

0.2 REST API [내부링크]

Response JSON 0.2.1 Response JSON Response 1. HTML 응답 문서(HTML) 한 장을 응답하는 서버 HTML template을 만들어 응답 해오던 방식 'Content-Type' entity header 리소스의 media type(MIME type, content type)을 나타내기 위해 사용된다. 응답 내에 있는 콘텐츠의 콘텐츠 유형이 실제로 무엇인지 클라이언트에게 알려준다. 2. JsonResponse()를 사용한 JSON 응답 문서(HTML) 한 장을 응답하는 것이 아닌 JSON 데이터를 응답 Django가 기본적으로 제공하는 JsonResponse 객체를 활용하여 Python 데이터 타입을 손쉽게 JSON으로 변환하여 응답이 가능하다. JsonResponse() JSON-encoded response를 만드는 클래스 'safe' parameter 기본 값 : True False로 설정 시 모든 타입의 객체를 serialization 할

0.3 REST API [내부링크]

Django REST framework 0.3.1 Django REST framework - Single Model ModelSerializer articles / serializers.py 생성 serializers.py의 위치나 파일명은 자유롭게 작성 가능하다. ModelSerializer ModelSerializer 클래스는 모델 필드에 해당하는 필드가 있는 Serializer 클래스를 자동으로 만들 수 있는 shortcut을 제공한다. Model 정보에 맞춰 자동으로 필드를 생성 serializer에 대한 유요성 검사기를 자동으로 생성 .create() 및. update()의 간단한 기본 구현이 포함된다. Build RESTful API - Article HTTP requests methods를 활용하여 2개의 URL로 7개의 기능을 정의 " GET " List 'api_view' decorator DRF view 함수가 응답해야 하는 HTTP 메서드 목록을 받는다. 기본적으

0.4 REST API [내부링크]

Django REST framework - N:1 Relation 0.4.1 Django REST framework - N:1 GET - List GET - Detail POST DELETE & PUT N : 1 - 역참조 데이터 조회 1. 특정 게시글에 작성된 댓글 목록 출력하기 기존 필드 override - Article Detail 게시글 조회 시 해당 게시글의 댓글 목록까지 함께 출력하기 Serializer는 기존 필드를 override 하거나 추가적인 필드를 구성할 수 있다. 모델 관계상으로 참조 된 대상은 참조하는 대상의 표현에 포함되거나 중첩(nested) 될 수 있다. 중첩된 관계는 serializers를 필드로 사용하여 표현할 수 있다. 2. 특성 게시글에 작성된 댓글의 개수 출력 새로운 필드 추가 - Article Detail "게시글 조회 시 해당 게시글의 댓글 개수까지 함께 출력하기" source serializers field's argument 필드를 채우는

0.1 JavaScript [내부링크]

JavaScript 0.1.1 JavaScript 시작하기 실행하기 1. Web Browser로 실행하기 방법 (1) 방법 (2) 결과 확인 방법 (3) 2. Node.JavaScript로 실행하기

0.2 JavaScript [내부링크]

JavaScript 기본 문법 -1 0.2.1 JavaScript 기본 문법 - 1 코드 작성법 세미콜론 (semicolon) 자바스크립트는 세미콜론을 선택적으로 사용 가능하다. 세미콜론이 없으면 ASI에 의해 자동으로 세미콜론이 삽입된다. ASI (Automatic Semicolon Insertion, 자동 세미콜론 삽입 규칙) 들여쓰기와 코드 블럭 javaScript는 2칸 들여쓰기를 사용한다. 블럭(block)은 if, for, 함수에서 중괄호 { } 내부를 말한다. python은 들여쓰기를 이용해 코드 블럭을 구분 JavaScript는 중괄호 {}를 사용해 코드 블럭을 구분 코드 스타일 가이드 JavaScript는 여러 코드 스타일 가이드가 회사마다 존재한다. ex) Airbnb JavaScript Style Guide Google JavaScript Style Guide standardJavaScript 주석 한 줄 주석 (//) 과 여러 줄 (/**/) 주석 변수와 식별자

0.3 JavaScript [내부링크]

JavaScript 기본 문법 0.3.1 JavaScript 기본 문법 - 2 함수의 정의 함수 선언식 (Function declaration) 일반적인 프로그래밍 언어의 함수 정의 방식 ex) 실제 반환 값을 확인할려면 console.log(add(2,7))을 해야한다. 함수 표현식 (Function expression) 표현식 내에서 함수를 정의하는 방식 함수 표현식은 함수의 이름을 생략한 익명 함수로 정의 가능하다. 표현식에서 함수 이름을 명시하는 것도 가능하다. 이 경우 함수 이름은 호출에 사용되지 못하고 디버깅 용도로 사용된다. ex) 기본 인자 인자 잣성 시 '=' 문자 뒤 기본 인자 선언 가능하다. 매개변수와 인자의 개수 불일치 허용 매개변수보다 인자의 개수가 많을 경우 매개변수보다 인자의 개수가 적을 경우 Spread syntax(...) '전개 구문' 전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 객체를 배열의 경우는 요소, 함수의 경우는 인자로 확장할 수

0.1 JavaScript 심화 [내부링크]

JavaScript 심화 0.1.1 DOM Browser APIs 웹 브라우저에 내장된 API로 현재 컴퓨터 환경에 관한 데이터를 제공하거나 여러 가지 유용하고 복잡한 일을 수행 종류 DOM Geolocation API - 지리 정보 API WebGL - 그래픽 API DOM 문서 객체 모델 (Document Object Model) 문서의 구조화된 표현을 제공하며 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공 문서 구조, 스타일, 내용 등을 변경할 수 있게 도움을 준다 HTML 콘텐츠를 추가, 제거, 변경하고, 동적으로 페이지에 스타일을 추가하는 등 HTML / CSS를 조작할 수 있다. 문서가 구조화되어 있으며 각 요소는 객체(object)로 취급한다. 단순한 속성 접근, 메서드 활용뿐만 아니라 프로그래밍 언어적 특성을 활용한 조작이 가능하다. DOM은 문서를 논리 트리로 표현한다. DOM 메서드를 사용하면 프로그래밍적으로 트리에 접근할 수 있고 이를 통해 문서의

0.2 JavaScript 심화 [내부링크]

JavaScript 심화 0.2.1 Event Event object 네트워크 활동이나 사용자와의 상호작용 같은 사건의 발생을 알리기 위한 객체 DOM 요소는 Event를 받고 받은 Event를 처리할 수 있다. Event 처리는 주로 addEventListener()라는 Event 처리기(Event handler)를 사용해 다양한 html 요소를 부착하게 된다. Event 발생 마우스를 클릭하거나 키보드를 누르는 등 사용자 행동으로 발생할 수도 있고 특정 메서드를 호출하여 프로그래밍적으로도 만들어 낼 수 있다. Event handler - addEventListener() EventTarget.addEventListener(type, listener[, options]) 지정한 Event가 대상에 전달될 때마다 호출할 함수를 설정 Event를 지원하는 모든 객체(Element, Document, Window 등)를 대상(EventTarget)으로 지정 가능하다. event.targ

0.1 Asynchronous JavaScript [내부링크]

Asynchronous JavaScript 0.1.1 동기와 비동기 동기 (Synchronous) 모든 일을 순서대로 하니씩 처리하는 것 비동기 (Asynchronous) 작업을 시작한 후 결과를 기다리지 않고 다음 작업을 처리하는 것 (병렬적 수행) 시간이 필요한 작업들은 요청을 보낸 뒤 응답이 빨리 오는 작업부터 처리 비동기를 사용하는 이유 사용자 경험 동기식 처리는 특정 로직이 실행되는 동안 다른 로직 실행을 차단하기 때문에 프로그램이 응답하지 않는 듯한 사용자 경험을 만들게 된다. 비동기로 처리한다면 먼저 처리되는 부분부터 보여줄 수 있으므로 사용자 경험에 긍정적인 효과를 볼 수 있다. 0.1.2 JavaScript의 비동기 처리 Single Thread 언어 JavaScript는 한 번에 하나의 일만 수행할 수 있는 Single Thread 언어로 동시에 여러 작업을 처리할 수 없다. Thread 작업을 처리할 때 실제로 작업을 수행하는 주체로, multi-thread라면

0.2 Asynchronous JavaScript [내부링크]

Asynchronous JavaScript 0.2.1 AJAX AJAX란 '비동기 통신 웹 개발 기술' 을 Asynchronous JavaScript And XML(AJAX)라 한다. AJAX의 특징 페이지 새로고침 없이 서버에 요청 서버로부터 응답(데이터)을 받아 작업을 수행 비동기 웹 통신을 위한 라이브러리 중 하나가 Axios 비동기 적용하기 script 코드를 작성하기 위한 block tag 영역 작성 axios CDN 작성 팔로우 (follow) form 요소 선택을 위해 id 속성 지정 및 선택 불필요해진 action과 method 속성은 삭제 (요청은 axios로 대체되기 때문에) form 요소에 이벤트 핸들러 작성 및 submit 이벤트 취소 axios 요청 준비 url에 작성할 user pk 가져오기 (HTML -> JS) data-* attributes 사용자 지정 데이터 특성을 만들어 임의의 데이터를 HTML과 DOM 사이에서 교환 할 수 있는 방법 사용 예시 d

0.1 Git 명령어 [내부링크]

※ Git 명령어 분류 명령어 내용 설명 <새로운 저장소 생성> $ git init .git 하위 디렉토리 생성 (폴더를 만든 후, 그 안에서 명령 실행 => 새로운 git저장소 생성) <저장소 복제/다운로드(clone)> $ git clone <https:.. URL> 기존 소스 코드 다운로드/복제 $ git clone /로컬/저장소/경로 로컬 저장소 복제 $ git clone 사용자명@호스트:/원격/저장소/경로 원격 서버 저장소 복제 <추가 및 확정(commit)> $ git add <파일명> 커밋에 단일 파일의 변경 사항을 포함 (인덱스에 추가된 상태) $ git add * 커밋에 단일 파일의 변경 사항을 포함 (인덱스에 추가된 상태) $ git add -A 커밋에 파일의 변경 사항을 한번에 모두 포함 $ git commit -m "커밋 메시지" 커밋 생성 (실제 변경사항 확정) $ git status 파일 상태 확인 <가지(branch)치기 작업> $ git branch 브랜

참사 [내부링크]

2022년 10월 30일 오늘은 주말에 있었던 이태원 참사로 인해 개인적인 일기는 일주일 뒤에 쓰겠습니다. 삼가 고인분들의 명복을 빕니다.

0.1 Vue CDN (기초) [내부링크]

Vue CDN 0.1.1 Vue intro 사전 준비 VSCode Vetur extension 설치 문법 하이라이팅, 자동완성, 디버깅 기능 제공 Chrome Vue devtools extension 설치 및 설정 크롬 브라우저 개발자 도구에서 vue 디버깅 기능 제공 Front-end Development Front-end (FE) 개발이란 사용자에게 보여주는 화면 만들기 Web App(SPA)을 만들 때 사용하는 도구 Web App(SPA) 웹 브라우저에서 실행되는 애플리케이션 소프트웨어 개발자 도구 > 디바이스 모드 웹 페이지가 그대로 보이는 것이 아닌 다비아스에 설치된 App처럼 보이는 것 웹 페이지가 디바이스에 맞는 적절한 UX/UI로 표현되는 형태 SPA Single Page Application 서버에서 최초 1장의 HTML만 전달받아 모든 요청에 대응하는 방식을 의미 CSR(Client Side Rendering) 방식으로 요청을 처리하기 때문에 가능 CSR (Clie

0.2 Vue CDN (기초) [내부링크]

Vue CDN 0.2.1 Vue를 사용하는 이유 Why Vue Vue 구조는 매우 직관적이다. FE Framework를 빠르고 쉽게 학습하고 활용 가능하다. Vue CDN Vue로 작업을 시작하기 위하여 CDN을 가져와야 한다. 사용 방법 Vue2 공식 문서에 접속 Get Started Installation Development version CDN 복사 후 이용 Vue로 코드 작성하기 Vue CDN 가져오기 Vue instance 생성 Vue instance 1개의 Object 정해진 속성명을 가진 Object el, data 설정 data에 관리할 속성 정의 선언적 렌더링 {{ }} Vue data를 화면에 렌더링 input tag에 v-model 작성 input에 값 입력 -> Vue data 반영 Vue data -> Dom 반영 Dev Tools 확인 Vue devtools에서 data 변경 > DOM 반영 눈에 보이는 화면을 조작하는 것이 아닌 Vue가 가진 data를

0.3 Vue CDN (기초) [내부링크]

Vue CDN 0.3.1 Basic of syntax Template Syntax 렌더링 된 DOM을 기본 Vue instance의 data에 선언적으로 바인딩 할 수 있는 HTML 기반 template syntax를 사용 렌더링 된 DOM - 브라우저에 의해 보기 좋게 그려질 HTML 코드 HTML 기반 template syntax - HTML 코드에 직접 작성할 수 있는 문법 제공 선언적으로 바인딩 - Vue instancd와 DOM을 연결 기본적인 바인딩(연결) 방법 중괄호 2개로 표기 DTL과 동일한 형태로 작성 Template interpolation 방법은 HTML을 일반 텍스트로 표현 RAW HTML v-html directive을 사용하여 data와 바인딩 directive - HTML 기반 template syntax HTML의 기본 속성이 아닌 Vue가 제공하는 특수 속성의 값으로 data를 작성 JS 표현식 표현식 형태로 작성 가능하다. Directives v-접

0.4 Vue CDN (기초) [내부링크]

Vue CDN 0.4.1 Vue advanced computed Vue instance가 가진 options 중 하나 computed 객체에 정의한 함수를 페이지가 최초로 렌더링 될 때 호출하여 계산 계산 결과가 변하기 전까지 함수를 재호출하는 것이 아닌 계산된 값을 반환 method VS computed method 호출 될 때마다 함수를 실행 같은 결과여도 매번 새롭게 계산 computed 함수의 종속 대상의 변화에 따라 계산 여보가 결정된다. 종속 대상이 변하지 않으면 항상 저장(캐싱)된 값을 반환한다. watch 특정 데이터의 변화를 감지하는 기능 watch 객체를 정의 감시할 대상 data를 지정 data가 변할 시 실행 할 함수를 정의 첫 번째 인자는 변동 후 data 두 번째 인자는 변동 전 data 실행 함수를 Vue method로 대체 가능하다. 감시 대상 data의 이름으로 객체 생성 실행하고자 하는 method를 handler에 문자열 형태로 할당 filters

0.1Vue CLI [내부링크]

Vue CLI 0.1.1 Vue CLI Vue CLI Vue 개발을 위한 표준 도구 프로젝트의 구성을 도와주는 역할 확장 플로그인, GUI, Babel 등 다양한 tool을 제공한다. Vue CLI 설치 설치 프로젝트 생성 프로젝트 디렉터리로 이동 프로젝트 실행 Vue CLI 프로젝트 구조 node_modules node.js 환경의 여러 의존성 모듈 python의 venv와 비슷한 역할을 한다. gitigmore에 넣어주어야 하며, Vue 프로젝트를 생성하면 자동으로 추가된다. node_modules-Babel JavaScript compiler 자바스크립트의 ES6+ 코드를 구 버전으로 번역/변환해 주는 도구 node_modules-Webpack static module bundler 모듈 간의 의존성 문제를 해결하기 위한 도구 프로젝트에 필요한 모든 모듈을 매핑하고 내부적으로 종속성 그래프를 빌드 한다. Module 모듈은 대개 기능 단위로 분리하며 클래스 하나 혹은 특정한 목

0.2 Vue CLI [내부링크]

Vue CLI 0.2.1 SFC component UI를 독립적이고 재사용 가능한 조각들로 나눈 것 기능별로 분화한 코드 조각 CS에서는 다시 사용할 수 있는 범용성을 위해 개발된 소프트웨어 구성 요소를 의미 하나의 app을 구성할 때 중첩된 컴포넌트들의 tree로 구성하는 것이 보편적이다. Component based architecture 특징 관리가 용이 유지/ 보수 비용 감소 재사용성 확장 가능 캡슐화 독립적 SFC 하나의. vue 파일이 하나의 Vue instance이고, 하나의 컴포넌트이다. 즉, Single File Component HTML, CSS, JavaScript를. vue라는 확장자를 가진 파일 안에서 개발하며 관리 Vue component 템플릿 (HTML) HTML의 body 부분 눈으로 보이는 요소 작성 다른 컴포넌트를 HTML 요소처럼 추가 가능 스크립트 (JavaScript) JavaScript 코드가 작성되는 곳 컴포넌트 정보, 데이터, 메서드 등

0.3 Vue CLI [내부링크]

Vue CLI 0.3.1 Pass Props & Emit Events Data in components pass props & emit event 부모 => 자식으로의 데이터의 흐름 pass props의 방식 자식 => 부모로의 데이터의 흐름 emit event의 방식 Pass Props 요소의 속성(property)을 사용하여 데이터 전달 props는 부모(상위) 컴포넌트의 정보를 전달하기 위한 사용자 지정 특성 자식(하위) 컴포넌트는 props 옵션을 사용하여 수신하는 props를 명시적으로 선언해야 한다. 정적인 데이터를 전달하는 경우 static props라고 명시하기도 한다. 요소에 속성을 작성하듯이 사용 가능하여, prop-data-name='value'의 형태로 데이터를 전달 이때 속성의 키값은 kebab-case를 사용한다. Pass Props convention 부모에서 넘겨주는 props kebab-case HTML 속성명은 대소문자를 구분하지 않기 때문에 자식에서

0.1 Git / Git Advanced [내부링크]

Git / Git Advanced 0.1.1 Git undoing git restore working Directory에서 수정 전(직전 커밋) 파일로 되돌리기 이미 버전 관리가 되어 있는 파일만 되돌리기 가능 git restore를 통해 되돌리면, 해당 내용을 복원할 수 없다. git restore {파일 이름} Staging Area 작업 단계 되돌리기 Repository 작업 단계 되돌리기 i를 누르면 INSERT 모드 ESC를 누르면 INSERT 모드를 나와 command모드가 된다. command 모드 :wq - 저장하고 종료 :q - 바로 종료 Git reset / Git revert Git reset Git revert Reset과 Revert의 차이점

0.1 Git / Git Advanced [내부링크]

Git / Git Advanced 0.2.1 Git branch Git branch 나뭇가지라는 뜻으로 여러 갈래로 작업 공간을 나누어 독립적으로 작업할 수 있도록 도와주는 Git의 도구 장점 branch관련 명령어 switch관련 명령어 Git merge Fast-Forward 빨리감기처럼 브랜치가 가리키는 커밋을 앞으로 이동시키는 방법 (master) $git merge hotfix 3-way Merge 각 브랜치의 커밋 두 개와 공통 조상 하나를 사용하여 병합하는 방법 (master) $ git merge hotfix 같은 부분을 수정하면 충돌이 발생하는데 수정 후 저장하면 된다.

0.1 Git / Git Advanced [내부링크]

Git / Git Advanced 0.3.1 Git workflow Git workflow shared repository model 원격 저장소를 로컬 저장소에 clone 받는다. 각각의 기능마다 branch를 만든다. 각각의 기능을 각각의 브랜치에 저장한다. 브랜치를 Merge requests(git마다 이름이 다르다.)로 master에 병합한다. 브랜치를 삭제한 뒤 병합된 master을 기준으로 다시 branch를 만들어 작업한다. Fork & Pull model Git 브랜치 전략

힐링 [내부링크]

2022년 11월 06일 말 그대로 힐링이었다. 오늘 같이 추운 날 따뜻한 물에 들어가 몸을 녹이니 일주일의 피로가 싹 없어지는 기분이었다. 스파를 마친 후 간 찜질방도 너무 좋았다. 특히 28도로 맞추어진 편백나무 방은 인상적인 기억이었다. 편백나무의 향과 적절한 온도가 내 몸을 감싸면서 나도 모르게 스르르 잠에 들었다. 이렇게 하루를 보내고 나니 완벽한 하루를 보냈단 기분이 들었다. 스파를 간 토요일도 날이 좋았지만 다음 날인 일요일도 날이 너무 좋아 쿠키랑 산책을 나갔다. 쿠키도 떨어지는 단풍을 밟으며 신나게 산책을 하는 것 같아 내가 더 기분이 좋아졌다. 이번 주말은 평화롭고 행복한 기억으로 남을 것 같다.

0.1 Vuex [내부링크]

Vuex 0.1.1 Vuex state Management 상태(State)란 현재에 대한 정보(data) 상태 관리 각 component는 독립적이기 때문에 각각의 상태(data)를 가진다. 여러 개의 component가 같은 상태(data)를 유지할 필요가 있다. Pass Props & Emit Event 각 컴포넌트는 독립적으로 데이터를 관리 같은 데이터를 공유하고 있으므로 각 컴포넌트가 동일한 상태를 유지하고 있다. component의 중첩이 깊어지면 데이터 전달이 쉽지 않다. Centralized Store 중앙 저장소 (store)에 데이터를 모아서 상태 관리 각 component는 중앙 저장소의 데이터를 사용한다. component의 계층에 상관없이 중앙 저장소에 접근해서 데이터를 얻거나 변경할 수 있다. Vuex "state management pattern + Library" 생태 관리 패턴 + 라이브러리 중앙 저장소를 통해 상태 관리를 할 수 있도록 하는 라이브러리

0.2 Vuex [내부링크]

Vuex 0.2.1 Lifecycle Hooks Lifecycle Hooks 각 vue 인스턴스는 생성과 소멸의 과정 중 단계별 초기화 과정을 거친다. 각 단계가 트리거가 되어 특정 로직을 실행할 수 있다. beforeCreate Vue 인스턴스가 초기화 된 직후에 발생 컴포넌트가 DOM에 추가되기 전이라 this.$el, data, methods에 접근할 수 없다. created Vue instance가 생성된 후 호출된다. data, computed 등의 설정이 완료된 상태 서버에서 받은 데이터를 vue instance의 data에 할당하는 로직을 구현하기 적합하다. mount되지 않아 요소에 접근할 수 없다. DOM에 추가된 상태가 아니다. created 함수를 이용해 버튼을 누르지 않아도 강아지 사진을 가져오는 함수를 추가 beforeMount DOM에 부착하기 직전에 호출 가상 DOM이 생성되어 있으나 실제 DOM에 부착되지는 않은 상태 mounted Vue instance

0.1 Vue Router [내부링크]

Vue Router 0.1.1 UX & UI UX (User Experience) 유저와 가장 가까이에 있는 분야, 데이터를 기반으로 유저를 조사하고 분석해서 개발자, 디자이너가 이해할 수 있게 소통 유저가 느끼는 느낌, 태도, 행동을 디자인 좋은 UX를 설계하기 위해서 사람들의 마을과 생각을 이해하고 정리해서 제품에 녹여내는 과정이 필요하다. 유저 리서치, 데이터 설계 및 정제, 유저 시나리오, 프로토타입 설계 등이 필요하다. UI (User Interface) 유저에게 보여지는 화면을 디자인 UX를 고려한 디자인을 반영, 이 과정에서 기능 개선 혹은 추가가 필요한 경우 Front-end 개발자와 가장 많이 소통한다. Interface 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점 사용자가 기기를 쉽게 동작 시키는데 도움을 주는 시스템 좋은 UI를 설계하기 위해서 심미적인 부분만 중요하기보다 사용자가 쉽고 편리하게 사용할 수 있도록 하는 부분까지 고

0.2 Vue Router [내부링크]

Vue Router 0.2.1 Navigation Guard 네비게이션 가드 Vue router를 통해 특정 URL에 접근할 때 다른 url로 redirect를 하거나 해당 URL로의 접근을 막는 방법 네비게이션 가드의 종류 전역 가드 애플리케이션 전역에서 동작 라우터 가드 특정 URL에서만 동작 컴포넌트 가드 라우터 컴포넌트 안에 정의 전역 가드 다른 url 주소로 이동할 때 항상 실행 router/index.js에 router.beforeEach()를 사용하여 설정 router 객체 아랫쪽에 작성한다. 콜백 함수의 값으로 3개의 인자를 받는다. to : 이동할 URL 정보가 담긴 Route 객체 from : 현재 URL 정보가 담긴 Route 객체 next : 지정한 URL로 이동하기 위해 호출하는 함수 콜백 함수 내부에서 반드시 한 번만 호출되어야 한다. 기본적으로 to에 해당하는 URL로 이동 URL이 변경되어 화면이 전환되기 전 router.beforeEach()가 호출된다

색다른 경험 (feat. 빈티지) [내부링크]

2022년 11월 13일 토요일에 처음으로 빈티지한 옷을 파는 곳에 가보았다. 공장 컨테이너 같은 곳에서 수많은 옷이 있어 규모에 놀랐다. 내부는 옷걸이에 진열된 옷들과 옷으로 산을 쌓은 부분이 있었다. 옷의 양이 상당해 처음에는 선택하기가 힘들었지만 천천히 둘러보면서 상태와 스타일이 괜찮은 옷들이 몇 개 있어 입어보기도 하면서 쇼핑을 하였다. 옷 산은 신발을 벗고 이용할 수 있었는데 막상 들어가서 파헤쳐 보니 괜찮은 옷들이 꽤 있어 찾는 재미가 있었다. 옷 산에서 찍은 사진 오전, 오후에는 쇼핑을 하고 저녁에는 날이 선선해서 쿠키와 함께 산책을 나갔다. 산책하기 좋은 날이라 2시간가량을 공원에서 뛰어놀았다. 일기예보에는 비가 예정되어 있어 사람들이 많이 없었지만 오히려 조용하고 편안한 분위기가 느껴지는 날이었다.

오랜만에 방문한 부싼! [내부링크]

2022년 11월 27일 오랜만에 여유가 생겨 친구들과 부산에 다녀왔다. 겨울 바다라 추울 것 같았지만 이게 무슨 일인가 날씨가 말도 안 되게 따뜻했다. 바다에 내리쬐는 햇볕은 너무 눈부셨고 바라만 봐도 마음이 평온해졌다. 우리와 같은 생각으로 부산을 찾은 사람들이 많았다. 겨울이지만 여름과 같이 사람들이 사진을 찍고 여유를 즐기는 모습이 여행을 더 재미있게 만들어주었다. 항상 부산은 좋은 기억만 남기게 해주는 도시이다. 다시 여유가 생기면 부산에 와야겠다!

새로운 등장인물 [내부링크]

2022년 12월 04일 10월에 여자친구와 흑백 사진을 찍고 이번에는 여자친구와 새로운 친구 쿠키와 함께 컬러 사진을 찍었다. 원래 여자친구와 쿠키 둘만 찍기로 했는데 내가 같이 찍고 싶어서 같이 찍게 되었다. 둘이 찍을 때 보다 조금 더 신경 쓸게 많았지만 둘만 찍을 때와 다른 분위기의 사진이 나와서 너무 좋았다. 사진 찍을 때 고생한 우리 쿠키와 쿠키를 챙긴다고 많이 고생한 여자친구에게 고마웠다. 앞으로도 좋은 카메라로 이쁜 우리 모습을 많이 담아야겠다. 컬러 사진을 흑백으로 전환한 사진

7의 개수 - 프로그래머스 [내부링크]

// 정수 배열 array가 매개변수로 주어질 때, // 7이 총 몇 개 있는지 return function solution(array) { let result = 0 // 결과를 저장하는 변수 array.forEach((item, index, arr) => { const strItem = item + '' // 배열의 요소를 문자열로 변경 const regExp = /7/g // 정규 표현식을 활용해 7을 찾는다. const num = strItem.match(regExp) ?? 0 // 7을 찾은 배열 result += !num ? num : num.length }) return result } 정규 표현식 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어 문자열을 대상으로 패턴 매칭 기능을 제공한다. 특정 패턴과 일치하는 문자열을 검색하거나 추출 또는 치환할 수 있는 기능 플래그 정규 표현식의 검색 방식을 설정하기 위해 사용 i (Ignore case) :

OX퀴즈 - 프로그래머스 [내부링크]

// 수식들이 들어있는 문자열 배열 quiz가 주어진다. // 수식이 옳다면 O, 틀리다면 X를 return function solution(quiz) { const result = [] // 배열을 순회 quiz.forEach( item => { let number = null // 숫자를 저장하는 변수 let notNumber = null // 연산자를 저장하는 변수 let calNum = 0 // 현재까지 계산된 결과 const itemArr = item.split(' ') // 띄어쓰기 기준으로 문자열을 나눈다. itemArr.forEach( el => { if (!Number.isInteger(+el)) { // 연산자면 실행 notNumber = el } else if (Number.isInteger(+el) && el !== '=') { // 수면 실행 if (number !== null && notNumber !== null && notNumber === '-') {

가장 큰 수 찾기 - 프로그래머스 [내부링크]

// 정수 배열 array가 매개변수 // 가장 큰 수와 그 수의 인덱스를 담은 배열을 return function solution(array) { // 배열의 요소 중 최댓값을 구함 const maxNum = Math.max(...array) // 구한 최댓값으로 인덱스 값을 구함 const maxIdx = array.indexOf(maxNum) return [maxNum, maxIdx] } Math.max 전달받은 인수 중에서 가장 큰 수를 반환한다. 인수가 전달되지 않으면 -Infinity를 반환 배열을 인수로 전달받아 배열의 요소 중에서 최댓값을 구하려면 Function.prototype.apply 메서드 또는 스프레드 문법을 사용해야 한다. 스프레드 문법 하나로 문쳐 있는 여러 값들의 집합을 펼쳐서 개별적인 값들의 목록으로 만듦 사용할 수 있는 대상은 순회할 수 있는 이터러블에 한정

대문자와 소문자 - 프로그래머스 [내부링크]

// 문자열 my_string이 매개변수 // 대소문자를 서로 변경하여 return function solution(my_string) { let result = '' // 결과값 const regExp1 = /[A-Z]/ // 대문자 정규표현식 for (const word of my_string) { // 대문자면 소문자로 변경 if (regExp1.test(word)) { result += word.toLowerCase() } else { // 소문자면 대문자로 변경 result += word.toUpperCase() } } return result } 정규 표현식 범위 지정 [] 내에 -를 사용해 범위를 지정한다. [A-Z] : A ~ Z의 문자열 검색 [a-z] : a ~ z의 문자열 검색 [0-9] : 0 ~ 9의 문자열 검색 [A-Za-z] : A ~ Z 또는 a ~ z의 문자열 검색 RegExp.prototype.test 인수로 전달받은 문자열에 대해 정규 표현식의 패턴

문자열 계산하기 - 프로그래머스 [내부링크]

// 문자열 my_string이 매개변수로 주어질 때 // 수식을 계산한 값을 return // 연산자는 +, -만 존재 // 문자열의 시작과 끝에는 공백 x // 0으로 시작하는 숫자는 없다. // 잘못된 수식은 없다. // return 정수형 // 숫자와 연산자는 공백 하나로 구분 function solution(my_string) { // 수식을 판별하는 정규 표현식 const regExp = /[+-]/g; // 공백을 기준으로 문자열을 나눈 뒤 숫자만 뽑아 배열로 만든다. const strNumArr = my_string.split(' ').filter(item => !regExp.test(item)); // 수식만 모은 배열 const strCalArr = my_string.match(regExp); // 결과값 (초기값을 숫자 배열의 첫 번째 값으로 설정하여 수식과 수의 갯수를 맞춘다.) let result = Number(strNumArr[0]); for (let n

문자열 밀기 - 프로그래머스 [내부링크]

// 문자열 A를 오른쪽으로 몇 번 밀어서 B가 될 수 있는지 return // 될 수 없다면 -1을 return function solution(A, B) { const ALength = A.length let result = -1 let currentStr = A.slice() if (A===B) { return 0 } for (let i = 1; i < ALength; i++) { currentStr = currentStr[ALength-1] + currentStr.slice(0,ALength-1) if (currentStr === B) { result = i break } } return result } String.prototype.slice substring 메서드와 동일하게 동작, slice 메서드에는 음수인 인수를 전달할 수 있다. 음수인 인수를 전달하면 대상 문자열의 가장 뒤에서부터 시작하여 문자열을 잘라내어 반환 length 문자열의 문자 개수를 반환

문자열 정렬하기 - 프로그래머스 [내부링크]

// 대소문자로 이루어진 문자열 매개변수로 주어짐 // 모두 소문자로 바꾸고 알파벳 순서대로 정렬한 뒤 return function solution(my_string) { const result = my_string.toLowerCase().split('').sort().join('') return result } String.prototype.toLowerCase 대상 문자열을 모두 소문자로 변경한 문자열을 반환 String.prototype.split 대상 문자열에서 첫 번째 인수로 전달한 문자열 또는 정규 표현식을 검색하여 문자열을 구분한 후 분리된 각 문자열로 이루어진 배열을 반환 빈 문자열을 전달하면 각 문자를 모두 분리하고, 인수를 생략하면 대상 문자열 전체를 단일 요소로 하는 배열을 반환 Array.prototype.join 원본 배열의 모든 요소를 문자열로 변환한 후, 인수로 전달받은 문자열, 구분자로 연결한 문자열로 반환 구분자는 생략 가능하며 기본 구분자는 콤마다.

배열의 유사도 - 프로그래머스 [내부링크]

// 문자열 배열 s1, s2의 같은 원소의 개수를 return function solution(s1, s2) { let count = 0 for (const st of s1) { // 한 개의 배열을 순회하여 // 나머지 한 개의 배열에 요소가 존재하는지 확인 s2.indexOf(st) !== -1 ? ++count : null } return count } Array.prototype.indexOf 원본 배열에서 인수로 전달된 요소를 검색하여 인덱스를 반환 원본 배열에 인수로 전달한 요소와 중복되는 요소가 여러 개 있다면 첫 번째로 검색된 요소의 인덱스를 반환 원본 배열에 인수로 전달한 요소가 존재하지 않으면 -1을 반환

숫자 찾기 - 프로그래머스 [내부링크]

// 정수 num, k가 매개변수 // num을 이루는 숫자 중에 k가 있으면 // 숫자가 있는 자리 수를 return // 없으면 -1 function solution(num, k) { // 정수를 문자열로 변경 const numStr = num + '' // 같은 숫자가 존재하면 인덱스 값에 +1, 없으면 -1을 return return numStr.indexOf(k) !== -1 ? numStr.indexOf(k) + 1 : -1 } Array.prototype.indexOf 원본 배열에서 인수로 전달된 요소를 검색하여 인덱스를 반환 인수로 전달한 요소와 중복되는 요소가 여러 개 있다면 첫 번째로 검색된 요소의 인덱스를 반환 인수로 전달한 요소가 존재하지 않으면 -1을 반환

약수 구하기 - 프로그래머스 [내부링크]

// 정수 n이 매개변수 // n의 약수를 오름차순으로 담은 배열을 return function solution(n) { const result = [] // 결과값 for (let i = 0; i <= n; i++) { // n이하의 수를 반복해 약수이면 배열에 넣고 아니면 null을 반환 n % i === 0 ? result[result.length] = i : null } return result }

연속된 수의 합 - 프로그래머스 [내부링크]

// 두 정수 num과 total이 주어집니다. // 연속된 수 num개를 더한 값이 total이 될 때, // 정수 배열을 오름차순으로 담아 return // total이 될 수 없는 테이스 케이스는 없다. function solution(num, total) { let result = []; if (!(total % num)) { const divNum = total / num // total을 num으로 나눈 수 result = [divNum] // 결과를 반환하는 Array, 중앙 값을 기준으로 Array를 구한다. const cnt = (num-1) / 2 // 중앙 값에서 몇 번 1을 빼야하는지 counting하는 변수 for (let i = 0; i < cnt; i++) { result.unshift(result[0] - 1) result.push(result[result.length-1] + 1) } } else{ const divNum = Math.floor(tota

영어가 싫어요 - 프로그래머스 [내부링크]

// 영어로 표기되어있는 숫자를 수로 바꾼다. // 문자열 numbers가 매개변수 // numbers를 정수로 바꿔 return function solution(numbers) { let result = '' // 결과값 // 숫자를 판단할 Object const number = { 'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7, 'eight': 8, 'nine': 9 } // 인수를 순회하면서 object에 포함되는지 체크 // 포함되면 결과값에 추가 let st = '' for (const word of numbers) { st += word if (number[st] !== undefined) { result += number[st] st = '' } } return +result //결과값을 숫자로 바꿔서 return }

인덱스 바꾸기 - 프로그래머스 [내부링크]

// 문자열 my_string, num1, num2가 매개변수 // my_string에서 인덱스 num1과 인덱스 num2에 해당하는 // 문자를 바꾼 문자열을 return function solution(my_string, num1, num2) { const str1 = my_string[num1] // num1 인덱스의 문자 const str2 = my_string[num2] // num2 인덱스의 문자 const strArr = my_string.split('') // 문자열을 배열로 바꾼다. strArr.splice(num1,1,str2) // 서로 인덱스 값을 교환한다. strArr.splice(num2,1,str1) return strArr.join('') } String.prototype.split 대상 문자열에서 첫 번째 인수로 전달한 문자열 또는 정규 표현식을 검색하여 문자열을 구분한 후 분리된 각 문자열로 이루어진 배열을 반환 빈 문자열을 전달하면 각 문자를 모두

잘라서 배열로 저장하기 - 프로그래머스 [내부링크]

// my_str을 길이 n씩 잘라서 저장한 배열을 return function solution(my_str, n) { const result = [] // 자른 배열을 저장하는 변수 const strLength = my_str.length // 문자열 길이 const count = Math.ceil(strLength / n) // 몇 번 잘라야 하는지 나타내는 변수 for (let i = 0; i < count; i++) { // 남은 길이가 잘라야하는 길이보다 짧으면 전부 다 자름 if (strLength-i*n < n) { result[i] = my_str.slice(i*n, strLength) } // 아니라면 n만큼 자름 result[i] = my_str.slice(i*n,i*n+n) } return result } Math.ceil 인수로 전달된 숫자의 소수점 이하를 올림한 정수를 반환

제곱수 판별하기 - 프로그래머스 [내부링크]

// 정수 n이 제곱수라면 1을 반환 // 아니면 2를 반환 function solution(n) { const number = Math.sqrt(n) return number - Math.floor(number) === 0 ? 1 : 2 } Math.sqrt 인수로 전달된 숫자의 제곱근을 반환 Math.floor 인수로 전달된 숫자의 소수점 이하를 내림한 정수를 반환

종이 자르기 - 프로그래머스 [내부링크]

// 정수 M, N이 매개변수 // 1*1로 만들기 위한 최소로 가위질 해야하는 횟수를 return function solution(M,N) { // 두 수를 곱한 값이 만들 수 있는 사각형의 개수이다. // 사각형의 개수 - 1번을 자르면 1*1의 사각형들을 만들 수 있다. return M*N !== 1? M*N-1 : 0 }

한번만 등장한 문자 - 프로그래머스 [내부링크]

// 문자열 s가 매개변수로 주어진다. // s에서 한 번만 등장하는 문자를 사전 순으로 // 정렬한 문자열을 return function solution(s) { const result = [] // 결과값 const sameStr = [] // 같은 문자를 저장하는 배열 for (const st of s) { // 결과값에 문자열이 존재하지 않으면 추가 if (result.indexOf(st) === -1 && sameStr.indexOf(st) === -1) { result[result.length] = st // 같은 문자열이 존재하면 제거하고 같은 문자열을 저장하는 배열에 저장 } else if(result.indexOf(st) !== -1 && sameStr.indexOf(st) === -1){ sameStr[sameStr.length] = st const idx = result.indexOf(st) result.splice(idx,1) } } return result.s

암호 해독 - 프로그래머스 [내부링크]

// 문자열 cipher와 정수 code가 매개변수 // cipher에서 code의 배수 번째 글자만 진짜 암호 // 해독된 암호 문자열을 return function solution(cipher, code) { let result = '' // 결과값 // cipher에서 code의 배수 번째 글자를 찾아 result에 더한다. for (let i = 0; i < cipher.length; i++) { // i+1이 code의 배수인지 확인 (i+1) % code === 0 ? result += cipher[i] : null } return result } 삼항 조건 연산자 ? 왼쪽의 표현식이 true이면 :의 왼쪽 식을 수행하고 false이면 :의 오른쪽 식을 수행한다.

369게임 - 프로그래머 [내부링크]

// 369게임에서 머쓱이가 말해야하는 숫자 order가 매개변수 // 쳐야할 박수 횟수를 return function solution(order) { // 숫자값 order를 문자열로 변경한 뒤 정규 표현식으로 3,6,9가 // 들어가는 배열을 반환한 뒤 길이를 구한다. const regExp = /[369]/g // 3,6,9 정규 표현식 const result = ('' + order).match(regExp) // 3,6,9가 포함된 배열 return result === null ? 0 : result.length // 배열이 null이면 0 아니면 길이를 반환 } 처음에 null인 경우를 고려하지 않아 테스트 케이스가 2개 틀렸다. 밑에는 null을 고려하지 않고 짠 코드 // 369게임에서 머쓱이가 말해야하는 숫자 order가 매개변수 // 쳐야할 박수 횟수를 return function solution(order) { // 숫자값 order를 문자열로 변경한 뒤 정규 표

가까운 수 - 프로그래머스 [내부링크]

// 정수 배열 array, 정수 n이 매개변수 // array에 들어있는 정수 중 n과 가장 가까운 수를 return function solution(array, n) { let result = 0; // 결과값 let minSub = Number.MAX_SAFE_INTEGER; // 두 수의 차를 저장하는 변수 // 초기값은 큰 수로 정하다. // 정수 배열을 순회하면서 n과 현재 수의 차를 구하고 전에 // 저장되어있던 차보다 작으면 결과값을 바꾼다. // 만약 가까운 수가 같다면 더 작은 수를 result에 저장한다. array.forEach(item => { if (minSub > Math.abs(item - n)) { minSub = Math.abs(item - n); result = item } else if (minSub === Math.abs(item - n) && result > item) { result = item } }) return result } Numbe

삼각형의 완성 조건 - 프로그래머스 [내부링크]

// 삼각형의 세 변의 길이가 담긴 배열 sides가 매개변수 // 세 변으로 삼각형을 만들 수 있다면 1, 없다면 2를 return // 삼각형의 조건 : 가장 긴 변의 길이는 다른 두 변의 길이의 합보다 작아야한다. function solution(sides) { // 1. 배열에서 가장 큰 수를 찾는다. const maxV = Math.max(...sides); // 2. 배열의 합을 구한다. const sumV = sides.reduce((preV, curV) => { return preV + curV; },0) // 3. 두 수의 합을 구한다. const otherNumSum = sumV - maxV; // 4. 결과를 구한다. return maxV >= otherNumSum ? 2 : 1 } Math.max 전달받은 인수 중에서 가장 큰 수를 반환 인수가 전달되지 않으면 -Infinity를 반환 배열을 인수로 전달받아 배열의 요소 중에서 최대값을 구하려면 Function.

중복된 문자 제거 - 프로그래머스 [내부링크]

// 문자열 my_string이 매개변수 // 중복된 문자를 제거하고 하나의 문자만 // 남긴 문자열을 return function solution(my_string) { // 1. 문자열을 배열로 바꾼다. const strArr = my_string.split(""); // 2. reduce를 이용해 중복을 제거한다. const result = strArr.reduce((pre, cur) => { // 문자열이 중복되면 추가하지 않는다. return pre.indexOf(cur) === -1 ? pre + cur : pre; }, ""); return result; } Array.prototype.reduce 콜백 함수의 반환값을 다음 순회 시에 콜백 함수의 첫 번째 인수로 전달하면서 콜백 함수를 호출하여 하나의 결과값을 만들어 반환한다. 첫 번째 인수로 콜백 함수, 두 번째 인수로 초기값을 전달받는다. 콜백 함수에는 4개의 인수 - 초기값 or 콜백 함수의 이전 반환값 , 배열의

K의 개수 - 프로그래머스 [내부링크]

// 정수 i, j, k가 매개변수로 주어진다. // i부터 j까지 k가 몇 번 등장하는지 return function solution(i, j, k) { let result = 0; // 결과값 // 1. for문을 이용해 i ~ j + 1까지 수를 반복 for (let start = i; start < j + 1; start++) { const strStart = start + ""; // 수를 문자열로 변경 // 2. 문자열을 순회하면서 k와 같은 문자가 있으면 result를 1증가 // for (const str of strStart) { // str === String(k) ? result++ : null; // } // 2-1. forEach를 사용한 방법 [...strStart].forEach((str) => { str === String(k) ? result++ : null; }); } return result; } 문자열에 forEach를 적용할려면 배열로 변경해야

A로 B 만들기 - 프로그래머스 [내부링크]

// 문자열 before, after가 매개변수 // before의 순서를 바꾸어 after를 만들 수 있으면 // 1, 아니면 0 function solution(before, after) { // 1. befor의 문자들과 after 문자들을 배열로 변경 후 오름차순으로 정렬 const beforeArr = before.split("").sort(); const afterArr = after.split("").sort(); let result = 1; // 2. 반복문을 돌면서 두 배열의 index 값이 다르면 0 for (let n = 0; n < beforeArr.length; n++) { if (beforeArr[n] !== afterArr[n]) { result = 0; break; } } return result; } String.prototype.split 대상 문자열에서 첫 번째 인수로 전달한 문자열 또는 정규 표현식을 검색하여 문자열을 구분한 후 분리된 각 문자열로

이진수 더하기 - 프로그래머스 [내부링크]

// 이진수를 의미하는 두 개의 문자열 bin1, bin2가 매개변수 // 두 이진수의 합을 return function solution(bin1, bin2) { // 이진수를 숫자로 변환한 뒤 // 더하고 결과값을 다시 2진수로 변경 const bin1Num = parseInt(bin1, 2); const bin2Num = parseInt(bin2, 2); return (bin1Num + bin2Num).toString(2); } parseInt 문자열 인수를 정수로 해석하여 반환 인수가 문자열이 아니면 문자열로 변환한 다음, 정수로 해석하여 반환 두 번째 인수로 진법을 나타내는 기수를 전달할 수 있다. 첫 번째 문자열을 두 번째 기수로 해석한 뒤 그 결과를 10진수 정수로 반환한다. ex) parseInt('10', 2) => 2 Number.prototype.toString 10진수 숫자를 해당 기수의 문자열로 변환하여 반환하고 싶을 때 사용할 수 있다. ex) (15).toS

치킨 쿠폰 - 프로그래머스 [내부링크]

// 한 마리당 쿠폰 한 장 발급 // 쿠폰 열 장을 모으면 한 마리 서비스 // 서비스 치킨에도 쿠폰이 발급 // 시켜먹은 치킨의 수 chichen이 매개변수 // 최대 서비스 치킨의 수를 return function solution(chicken) { // 치킨의 초기 값은 1081장 let result = 0; let temp = chicken % 10; // 108개를 주문하면 쿠폰은 1개가 남는다. let answer = Math.floor(chicken / 10); // 108개의 닭 주문, 108 쿠폰 발급 result += answer; answer += temp; while (1) { temp = answer % 10; answer = Math.floor(answer / 10); // 10 result += answer; if (answer === 0) { break; } answer += temp; } return result; } console.log(soluti

React - State를 이용한 단위 변환기 만들기 [내부링크]

전체 코드 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <!-- React CDN --> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js" ></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ></script> <!-- babel CDN --> <script src="https://unpkg.com/@babel/standalone/bab

로그인 성공 - 프로그래머스 [내부링크]

// 아이디와 패스워드가 담긴 배열 id_pw // 회원들의 정보가 담긴 2차원 배열 db // 로그인 성공, 실패에 따른 메시지를 return // 아이디와 비밀번호가 모두 일치하는 회원정보가 있으면 login // 로그인이 실패했을 때 아이디가 일치하는 회원이 없다면 fail // 비밀번호가 일치하는 회원이 없다면 wrong pw function solution(id_pw, db) { let result = []; // 결과를 저장하는 배열 // db의 2차원 배열을 순회하면서 // 아이디와 비밀번호가 일치하면 2, 아이디는 일치하는데 비밀번호가 다르면 1, // 나머지는 0을 result 배열에 저장한다. for (const item of db) { if (id_pw[0] !== item[0] && id_pw[1] !== item[1]) { result[result.length] = 0; } else if (id_pw[0] !== item[0] && id_pw[1] === it

React - Coin Ticker [내부링크]

import { useEffect, useState } from "react"; function App() { const [loading, setLoading] = useState(true); const [coins, setCoins] = useState([]); useEffect(() => { fetch(" https://api.coinpaprika.com/v1/tickers") .then((response) => response.json()) .then((json) => { setCoins(json); setLoading(false); }); }, []); console.log(setLoading); return ( <div> <h1>The Coins! {loading ? "" : `(${coins.length})`}</h1> {loading ? ( <strong>Loading...</strong> ) : ( <select> {coins.map((coin) => { return

React - Movie App (part 1) [내부링크]

import { useState, useEffect } from "react"; function App() { const [loading, setLoading] = useState(true); const [movies, setMovies] = useState([]); const getMovies = async () => { const json = await ( await fetch(`https://yts.mx/api/v2/list_movies.json?minimum_rating=8.5`) ).json(); setMovies(json.data.movies); setLoading(false); }; useEffect(() => { getMovies(); }, []); return ( <div> {loading ? ( <h1>Loading...</h1> ) : ( <div> // 항상 map을 이용할 때는 key를 넣어줘야한다. {movies.map((movie) => { return (

등수매기기 - 프로그래머스 [내부링크]

// 영어 점수와 수학 점수의 평균으로 등수를 매김 // 영어 점수와 수학 점수를 담은 2차원 정수 배열 score // 매긴 등수를 담은 배열을 return function solution(score) { const result = []; // 결과값을 저장하는 배열 // 2차원 배열을 순회하며 평균과 index를 담은 averArr를 만든다. const averArr = score.map((scores, index) => { return [(scores[0] + scores[1]) / 2, index]; }); // 평균을 오름차순으로 정렬 averArr.sort((a, b) => b[0] - a[0]); let currentNum = 0; // 이전 성적을 저장한 변수 let cnt = 0; // 같은 점수인 학생을 확인하는 변수 let grade = 0; // 등수 averArr.forEach((item, index, arr) => { // 만약 이전 성적과 같으면 cnt를

특이한 정렬 - 프로그래머스 [내부링크]

// 정수 n을 기준으로 n과 가까운 수부터 정렬 // n과 거리가 같다면 더 큰 수를 앞에 오도록 배치 // 정수가 담긴 배열 numlist와 정수n // numlist의 원소를 n으로부터 가까운 순서대로 정렬한 배열 return function solution(numlist, n) { // numlist를 순회하면서 n과의 거리를 저장한다. numlist.forEach((item, index, arr) => { arr[index] = [item, Math.abs(item - n)]; }); // 저장한 뒤 2차원 배열이 된 numlist를 거리가 짧은 순으로 정렬한다. // 단 같은 값이면 더 큰 수를 앞으로 해서 정렬한다. numlist.sort((a, b) => { return a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : a[0] > b[0] ? -1 : 1; }); // 정렬된 numlist를 순회하면서 정수만 뽑아서 새로운 배열을 만든다. const

이산 수학 기초 [내부링크]

영상: https://www.youtube.com/playlist?list=PLRx0vPvlEmdDgOIBt9MKQl-uMVrxtac4n 1 강 이산 수학 개요 불연속적인 숫자를 다루는 수학 컴퓨터를 위한 수학, 참과 거짓으로 살펴보는 컴퓨터 수학, 전산, 정보 수학, 1 학년이나 처음 컴퓨터를 배우는 입장에서 배우게 됨, 자료구조 또는 알고리즘의 베이스, 논리적 사고, 컴퓨팅 사고력 향상 불연속적인 데이터의 흐름을 다루기에 적합한 수학적 사고를 배양하는데 필수적인 강의 컴퓨터 과학의 베이스 학문 2 강 명제와 연산자 명제 참 혹은 거짓으로 판단할 수 있는 문장 여러 개의 명제를 조합할 수 있다. ex) 11은 소수다. / 모기는 동물이다. 연산자 명제를 연산하기 위한 도구 이산 수학의 기본 연산자는 6 가지가 있다. Not 거짓 <-> 참으로 바꾼다. And 논리 곱 둘 다 참이면 참이다. Or 논리 합 둘 다 거짓이면 거짓이다. Exclusive or 배타적 논리합(서로를 배제한

React Hooks [내부링크]

React Hooks 사용규칙 같은 Hook을 여러번 호출할 수 있다. export default function App(){ const [value1, setValue1] = useState() const [value2, setValue2] = useState() return { <div> <div>{value1}</div> <div>{value2}</div> </div> } } 함수 컴포넌트 몸통이아닌, 몸통 안 복합 실행문의 {}에서는 사용할 수 없다. javascript의 block scope는, block 외에서 사용할 수 없으므로 ( 지역변수이기 때문에 ) export default function App(){ return { <div> // 불가능 <div>{const [value, setvalue] = useState()}</div> </div> } } 비동기 함수(async 키워드가 붙은 함수)는 콜백함수로 사용할 수 없다. export default function

Hooks 사용법 [내부링크]

useState 사용법 state란? React에서 사용자의 반응에 따라, 화면을 바꿔주기(렌더링) 위해 사용되는 트리거역할을 하는 변수 React가 state를 감시하고, 바뀐 정보에 따른 화면을 표시해준다. ( state와 setState함수의 반환값을 비교 ) state 만들기 (useState 사용) // React에 기본적으로 내장되어 있는 useState 훅을 사용하면, state를 만들 수 있다. import { useState } from "react"; // const [state, state변경함수] = useState(기본 state값); const [isLoggedIn, setIsLoggedIn] = useState(false); state 변경하기 (사용자 반응에 따른 다른 화면 보여주기) // 전에 만든 "isLoggedIn" state의 값을 true로 변경한다. setIsLoggedIn(true); // ** useState함수를 사용해 만든 "state

알아두면 좋은 HTML 태그 [내부링크]

progress <progress value="10" min="0" max="20"></progress> * 진행률 표시줄을 제공 * 두 개의 속성이 있다. - max, value meter <meter min="0" max="100" high="65" optimum="15" value="90"></meter> * 값이 높고, 낮을 때에 따라 색상이 바뀐다. * 값의 상태만 전달한다. - 진행 상태 전달 x * optimum : 최적의 값 detail / summary <details> <summary>내용</summary> <span>클릭한 후에 나오는 내용</span> </details> * 유저의 클릭으로 정보를 보여주고, 숨기는 패턴 * summary에는 유저가 클릭하기 전에 보이는 내용 * summary 후의 내용은 유저가 클릭했을 때 보이는 내용 * details에 open이라는 CSS selector가 있어 활용할 수 있다. input type <input type="w

React-query : useQuery [내부링크]

정의 서버의 값을 클라이언트에 가져오거나, 캐싱, 값, 업데이터, 에러핸들링 등 비동기 과정을 더욱 편하게 하는데 사용된다. 사용하는 이유 서버, 클라이언트 데이터를 분리 장점 캐싱 get 데이터에 대한 update를 하면 자동으로 get을 다시 수행 데이터가 오래 되었다고 판단되면 다시 get( invalidateQueries) 동일 데이터 여러번 요청하면 한 번만 요청 (옵션에 따라 중복 호출 허용, 시간 조절 가능) 무한 스크롤(Infinite Queries) 비동기 과정을 선언적으로 관리할 수 있다. 옵션 cacheTime 데이터가 inactive 상태일 때 캐싱된 상태로 남아있는 시간 쿼리 인스턴스가 unmount 되면 데이터는 inactive 상태로 변경되며, 캐시는 cacheTime만큼 유지된다. cacheTime이 지나면 가비지 콜렉터로 수집된다. cacheTime이 지나기 전에 쿼리 인스턴스가 다시 마운트 되면, 데이터를 fetch하는 동안 캐시 데이터를 보여준다.

React-query : useMutation [내부링크]

QueryCache 쿼리에 대해 성공, 실패 전처리를 할 수 있다. const queryClient = new QueryClient({ queryCache: new QueryCache({ onError: (error, query) => { console.log(error, query); if (query.state.data !== undefined) { toast.error(`에러가 났어요!!: ${error.message}`); }, }, onSuccess: data => { console.log(data) } }) }); import { from, useQuery } ' 'react-query'; function UserProfile() { const queryCache = new Query(); const { data, isLoading, error } = useQuery('user , () => { return fetch('/ ).then(res => res.json());

JavaScript로 표준 입력 받기 (readline 사용) [내부링크]

한 줄 값 입력 받기 const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.on("line", (line) => { rl.close(); }); rl.on("close", () => { process.exit(); }); 공백을 기준으로 값 입력 받기 const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); let input = [] rl.on("line", (line) => { input = line.split(' ').map(el => parseInt(el)); // 1 2 3 4 rl.close(); }); rl.on('close', ()

JavaScript로 표준 입력 받기 fs 모듈 사용) [내부링크]

한 줄 입력 let fs = require('fs'); let input = fs.readFileSync('/dev/stdin').toString().split(' '); let num = Number(input); for (let i = 1; i <= num; i++) { console.log(i); } 여러 줄 입력 let fs = require('fs'); let input = fs.readFileSync('/dev/stdin').toString().split('\n'); let count = input[0]; let numbers = []; for (let i = 1; i < input.length; i++) { if (input[i] !== '') { numbers.push(input[i].split(' ')); } } for (let i = 0; i < numbers.length; i++){ let num1 = Number(numbers[i][0]); let num2 =

Redux - ToDo(Vanilla JS) [내부링크]

전체 코드 <!-- todo.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=chrome" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.1.2/redux.js"></script> </head> <body> <div id="root"></div> <script src="./todo.js"></script> </body> </html> // todo.js const $root = document.getElementById("root"); const $h1 = document.creat

이산 수학: 셈(순열과 조합) - 곱의 법칙과 합의 법 [내부링크]

셈은 어떤 사건이 발생할 수 있는 경우의 수를 계산하는 것 두 개 이상의 사건의 경우의 수를 따질 때 두 사건이 서로 연계되어 발생 곱의 법칙을 적용하여 경우의 수를 계산 두 사건이 서로 아무런 상관없이 별도로 발생 합의 법칙을 적용하여 경우의 수를 계산 곱의 법칙 두 사건이 동시에 발생한다면 발생할 경우의 수는 n1 * n2가 된다. 합의 법칙 두 사건이 동시에 발생할 수 없다면 두 사건이 발생할 경우의 수는 n1 + n2가 된다. 동시에 라는 말의 의미가 반드시 시간적으로 동시에 발생한다는 의미는 아니다. 포함-배제 원리 어떤 문제에 있어서는 합의 법칙을 적용할 때 중복되어 계산된 경우의 수를 고려할 필요가 있다. 이 경우 중복되어 계산된 경우의 수를 제외해야 한다. E1 U E2 = E1 + E2 - E1^E2

이산수학 : 부울 대수와 논리 회로 설계 - 부울식의 최소화: 카르노 맵 [내부링크]

카르노 맵 부울 함수의 간단한 논리합 형식을 찾아내는 방법 두 변수 x, y를 갖는 부울식을 위한 카노우 맵은 사각형에서 2 * 2 개의 칸으로 구성된다. 각 칸은 부울 함수의 최소항을 의미한다. X X Y XY X`Y Y` XY` X`Y 부울 함수에서 해당 최소항이 있으면 그 칸을 1로 표시한다. X X` Y 1 Y` 1 1 부울식의 최소화 하나의 변수만이 다른 최소항들은 서로 인접한다고 한다. 카노우 맵에서 두 개의 인접한 칸이 1일 때 인접된 칸을 나타내는 최소항은 두 변수 중에서 공통된 변수 하나만으로 나타낼 수 있다. EX) x'y + x'y' = x'(y + y') = x' 이러한 성질을 이용하면 주어진 부울식에서 항의 수를 최소화할 수 있다. x x' y 1 1 y' => x와 x'이 서로 인접해 있으니 공통 변수 y로 나타낼 수 있다. 정리 카노우 맵을 만들 때 변수가 2개면 2 * 1, 변수가 3개면 4 * 2, 변수가 4개면 4 * 4 인접하는 칸들은 동일한 변수를

이산수학: 형식 언어와 문법 [내부링크]

언어 세 가지 요소로 구성된다. 기호들의 집합 S가 반드시 존재한다 - 알파벳 S 로부터 문장들의 집합 S*를 형성하는 규칙이 반드시 존재한다. - Syntax 규칙에 합당하게 만들어진 문장들이 의미를 갖는지를 결정할 수 있어야 한다. - Semantics Syntax(문법) 문장의 적합한 구성에 대한 규정 Semantics(의미론) 문장의 적합한 의미에 대한 규정 형식 언어 심벌 : 기호 알파벳 : 기호들의 유한 집합(V) 문자열 : 알파벳에 포함된 기호들이 나열된 것(V*) 공 문자열 : 길이가 0인 문자열, λ로 표시 (공집합 과는 다르다.) 구 - 구문 문법 V : 기호의 집합 = 비 단말 기호 T : 단말 기호 S : 시작 기호 P : 생성 규칙 (=>로 표시) 언어와 문법 문법 G의 언어 문법 G를 사용하여 만들어 질 수 있는 문장들의 집합 문법의 종류 유형 0 문법(비 제한 문법) 생성에 아무 제약이 없다. 유형 1 문법(문맥 의존 문법: context sensitive

JavaScript - JSDog [내부링크]

주석 어떤 기능을 하는지 명시해야 한다. 무슨 값을 return 하는지 명시해야 한다. JSDoc 함수를 사용할 때 힌트를 제공한다. 1. 시작 /** */ param 현재 파라미터의 설명을 적을 수 있다. 중괄호를 이용 파라미터의 권장 타입을 적을 수 있다. /** * @param {string} name 사람이름 */ returns 무엇을 return하는지 적을 수 있다. /** * @returns 두 개 합쳐서 문자로 뱉는다. */ see 해당 코드의 부과 정보를 적을 수 있다. /** * @see https://naver.com */ version 버전을 적을 수 있다. /** * @version 1.3.0 */ readonly 변수나 오브젝트 프로퍼티 위에 적으면 읽기 전용이라고 명시할 수 있다. 강제성은 없다. /** * @readonly * @const {number} */ const num = 1; todo 메모를 할 수 있다. /** * @todo 내일까지 할 일 *

JavaScript - 스크롤 애니메이션 [내부링크]

new IntersectionObserver() JavaScript의 기본 기능 비동기적으로 실행되기 때문에 렌더링 성능이나 이벤트 연속 호출같은 문제 없이 사용할 수 있다. HTML요소가 현재 보이는지 안보이는지 검사해볼 수 있다. <div>가 현재 화면에 보이는지 파악이 쉬워진다. 두 개의 인수를 가진다. 첫 번째 인자로 콜백 함수를 받는다. 감시중인 요소가 화면에 등장 & 퇴장하면 콜백함수가 실행된다. 요소.isIntersecting 화면에 요소가 보일 때 true 안보일 때 false 요소.isIntersectionRatio 화면에 요소가 몇 % 만큼 등장했는지 알려준다. 콜백함수는 2개의 인수(entries, observer)를 가진다. entries는 인스턴스의 배열이다. observer는 콜백함수가 실행되는 해당 인스턴스를 참조한다.4 두 번째 인자로 options를 가진다. Methods observe() 대상 요소의 관찰을 시작한다. unobserve() 대상 요소의

React - Page nation 구현 [내부링크]

개요 Redux와 React를 활용해 페이지네이션을 구현해보았다. 사실 Redux는 안써도 되지만 연습을 위해 일부로 사용해보았다. 코드 // PageNation.js import React from "react"; import { connect } from "react-redux"; import { useState } from "react"; function PageNation({ state }) { // 다음 버튼과 이전 버튼을 누르면 버튼 숫자를 바꾸어주기 위한 state const [currentBtn, setCurrentBtn] = useState(1); // 현재 페이지와 페이지를 변경하기 위한 state const [currentPage, setCurrentPage] = useState(1); // 다음 버튼을 누르면 버튼 숫자를 바꾸어준다. const getNextBtn = () => { if (currentBtn < state.length - 1) { setCurre

React - 무한 스크롤(Infinity scroll) [내부링크]

개요 React에서 무한 스크롤을 구현했지만 사실상 바닐라 JS로 구현한 것과 다를게 없다. 최근 진행 중인 프로젝트에서 사용될 예정이라 미리 연습해보았다. 코드 import React from "react"; import style from "../style/Home.module.css"; function Home() { let number = 3; // scroll 이벤트가 발생하면 실행되는 콜백함수 const toScroll = () => { // 새로운 div를 생성해서 추가한다. const $div = document.querySelector(".home"); const $el = document.createElement("div"); $el.className = style.box; if (window.innerHeight + window.scrollY >= document.body.offsetHeight) { number += 1; $el.textContent = numb

유한 소수 판별하기 - 프로그래머스 [내부링크]

// 분수를 소수로 고칠 때 // 유한소수로 나타낼 수 있는 분수인지 판별 // 조건 : 기약분수로 나타내었을 때, 분모의 소인수가 // 2와 5만 존재해야 한다. // 두 정수 a,b가 매개변수로 주어진다. // 유한소수 : 1, 무한소수: 2를 return function solution(a, b) { let cnt = 0; // a가 더 큰 경우 function func1(a, b) { cnt = b; // a와 b가 기약분수가 될 때까지 while문을 반복 while (cnt !== 1) { if (a % cnt === 0 && b % cnt === 0) { a /= cnt; b /= cnt; } else { cnt -= 1; } } // 분모가 1인 경우 무조건 유한소수 if (b === 1) { return 1; } // b가 1이 아닌 경우 2와 5가 아닌 수로 나누었을 때 나머지가 0인지 체크 for (let i = 3; i <= b; i++) { if (i !== 5

Emotion.js [내부링크]

개념 emotion.js는 CSS-in-JS의 종류 중 하나로 JavaScript 안에서 스타일을 작성할 수 있게 해준다. Framework를 사용하지 않는 것 React를 사용하는 것 두 가지가 있다. # Framework Agnostic $ npm install @emotion/css # React $ npm install @emotion/react 사용 /** @jsxImportSource @emotion/react */ import { jsx, css } from '@emotion/react' 위 코드를 import해야 사용할 수 있다. 사용 예시 /** @jsxImportSource @emotion/react */ import { css, jsx } from '@emotion/react' const styled = css` color: red; ` function Home() { return( <div css={styled}>Hello world</div> ) } expor

Redux-saga [내부링크]

미들웨어 리듀서가 액션이 디스패치된 다음 리듀서에서 해당 액션을 처리하기 전에 추가적인 작업을 할 수 있다. redux-saga 비동기 작업을 처리하기 위한 미들웨어 Thunk는 함수를 디스패치 할 수 있게 해주는 미들웨어, Saga는 액션을 모니터링 하고 있다가 특정 액션이 발생했을 때 미리 정해둔 로직에 따라 특정 작업이 이루어지는 방식 Sagas라는 순수 함수들로 로직을 처리할 수 있다. Thunk에 비해 많은 기능을 수행할 수 있다. Saga의 경우에는 기본적으로 제공하는 기능이 아니기 때문에, 이를 Store에 미들웨어로 등록해야 한다. Redux - Saga effects all all effect는 제너레이터 함수들이 들어있는 배열을 인자로 받습니다. 이렇게 들어온 제너레이터 함수들은 all effect 안에서 병렬적으로 기능을 수행하며, 이 함수들이 모두 resolve 될 때까지 기다립니다. Promise.all 과 비슷한 기능이라고 생각하시면 됩니다. call cal

JS 알고리즘 1일차 - 빅 오 표기 [내부링크]

인트로 좋은 코드는 많은 양의 메모리를 사용하지 않는 효율적인 코드를 쓰면서 읽기 쉬운 점 사이의 조율에서 나온다. 시간을 측정하는 것 보다 컴퓨터의 연산 개수를 측정하면 된다. Ex) 3*(2) / 2 → 연산이 총 3번이다. 즉 수가 엄청 커져도 총 연산은 3번이다. 하지만 반복문 안에 있는 연산은 반복문 수 만큼 증가한다. 시간 복잡도 - 빅 오 대략적으로 숫자를 세는 것에 붙인 공식적인 표현 입력된 내용이 늘어날 수록 알고리즘에 실행 시간이 어떻게 변하는지 설명하는 공식적인 방법 입력의 크기와 실행 시간의 관계 실행 시간이 갖을 수 있는 최대치를 말한다. 일반적으로 가장 높은 실행 시간 값들을 말한다. 즉, 전체적인 추세를 중요하게 여긴다. 표현 상수는 중요하지 않다. Ex) O(2n) ⇒ O(n)으로 표기한다. 작은 연산도 중요하지 않다. Ex) O(n+10) ⇒ O(n), O(n2 + 5n + 8) ⇒ O(n2) 규칙 항상 맞지는 않지만 쉽게 적용할 수 있는 규칙 산수는

JS 알고리즘 2일차 - 배열과 오브젝트의 성능 평가 [내부링크]

객체 정렬되어 있지 않은 데이터 구조, 모두 key와 value 짝을 갖고 저장되어있다. 사용할 때 정렬되어 있을 필요가 없을 때 잘 작동한다. 빠른 접근, 입력과 제거를 원할 때 좋다. 입력, 제거, 접근하는 시간이 상수 시간이다. 탐색은 선형 시간을 갖는다. 탐색은 key를 찾는 것이 아니다. 어떠한 정보에 접근하는 시간은 상수 시간이다. 객체는 매우 빠르다. 정렬되어 있지는 않지만 다른 것들은 매우 빠르다. 메소드 Object.keys 선형시간 - O(N) Object.values 선형시간 - O(N) Object. 선형시간 - O(N) HasOwnProperty O(1) 배열 정렬이 되어있다. 정렬되어 있는 것이 필요하면 유용하지만, 연산을 하는 시간이 더 걸릴 수 있다. 성능을 희생해야 할 수 있다. 입력과 제거할 때 복잡할 수 있다. 대부분 정렬되어 있는 데이터를 위해 사용한다. 정렬되어 있는 것이 필요 없다면 배열을 사용하지 않는 것이 좋다. 정렬되어 있는 것이 필요하더

JS 알고리즘 3일차 - 문제 해결 접근법 [내부링크]

알고리즘을 알아야 하는 이유? 프로그래밍에서 수행하는 거의 모든 작업에는 일종의 알고리즘이 포함되므로 문제를 해결할 방법을 마련할 수 있도록 결정을 해야 한다. 어떻게 공부해야 하나? 문제 해결을 위한 계획을 수립 문제를 세분화하기 위한 전력에 더 가깝다. 일반적으로 문제 해결 패턴을 파악한다. 문제 해결 전략 문제 이해하기 문제를 나만의 방식으로 만들 수 있는가? 문제에 들어갈 입력은 무엇인가? 문제에 대한 해결책에서 나와야 할 결과(출력)는 무엇인가? 입력 값이 출력값을 결정할 수 있는가? 문제의 일부인 데이터의 중요한 부분에 어떻게 라벨을 지정할 수 있는가? 정말 중요한 것은 무엇인가? 구체적 예시 살펴보기 간단한 예시로 시작한다. 더 복잡한 예시들은 무엇인가? 빈 입력값이 있는 예제를 살펴보는 것은 유효하지 않은 입력 값이 주어진 상황에서 문제를 어떻게 해결해야 할지 해결 능력을 갖출 수 있도록 해준다. 세부 분석(세분화) 해결책의 기본적인 구성 요소만 작성하면 된다. 코드

JS 알고리즘 4일차 - 문제 해결 패턴 소개 [내부링크]

빈도수 세기 패턴 JavaScript의 객체를 사용해서 다양한 값과 빈도를 수집하는 것 // arr1의 item의 제곱이 arr2의 item에 있으면서 갯수도 같아야한다. // 중첩된 루프를 사용한 해결책 function same(arr1, arr2) { if (arr1.length !== arr2.length) { return false; } for (let i = 0; i < arr1.length; i++) { let correctIndex = arr2.indexOf(arr1[i] ** 2) if (correctIndex === -1) { return false; } arr2.splice(correctIndex,1) } return true } - 시간복잡도 : O(n**2) ex) [1,2,3], [4,1,9] : true [1,2,1], [4,4,1] : false // 빈도 카운터 패턴을 사용한 코드 function same(arr1, arr2) { if (arr1.leng

JS 알고리즘 5일차 - 재귀(Recursion) [내부링크]

재귀 함수를 사용하는 이유 재귀란? 자기자신을 호출하는 절차(함수) 재귀는 모든 곳에서 사용된다. 스택 호출하기 거의 모든 프로그래밍 언어에는 보이지 않는 곳에서 함수 호출을 관리하는 일종의 데이터 구조가 있다. 호출된 함수는 다른 함수가 반환될 때까지 기다리는 경우가 많다. 즉, 함수는 올바른 순서대로 실행되야 한다. 이러한 것을 담당하는 데이터 구조를 JavaScript에서는 호출 스택이라 한다. 함수를 호출하면, 호출 스택의 맨 위에 쌓인다. 반환 키워드를 확인하거나, 함수 안에 더 이상 실행할 코드가 없으면 컴파일러가 스택의 제일 위에 있는 항목을 제거한다. 첫 번째 재귀함수 반드시 갖춰야 하는 두 가지 요소 기본적인 개념은 동일한 함수를 계속 호출하면서, 하나의 함수가 자기자신을 재귀적으로 호출하게 하는 것 죵료 조건이 존재해야 한다. 종료 조건은 재귀가 멈추는 시점이다. 재귀 함수의 두 가지 기본 요소 라인을 끝내는 종료 조건 다른 입력값 단순한 재귀 예시 function

JS 알고리즘 6일차 - 검색 알고리즘 [내부링크]

선형 검색 솔루션 function linearSearch(arr,val) { for (let i = 0; i < arr.length; i++) { if (arr[i] === val) { return i; } } return -1; } linearSearch([34, 56, 1, 2], 1) indexOf, findIndex, includes가 사용하는 알고리즘이다. 시간 복잡도 : O(n) 이진 검색 분류(정렬)된 배열을 대상으로만 작동하므로 데이터가 분류되어 있어야 한다. 기본적인 개념은 분할 정복이다. 보통 중간에 있는 중간점을 선택하고, 우리가 찾는 값이 중간점을 기준으로 좌측 절반과 우측 절반 중 어느 쪽에 있을지 확인한다. 이진 검색 의사 코드 분류된 배열을 인수로 전달받는 함수이다. 2개의 변수가 필요하다. 하나는 좌측을 또 다른 하나는 우측을 나타내는 인덱스로 포인터라고 한다. 포인터의 값은 배열의 길이에서 1을 뺀 값이다. 값을 찾으면 연산을 중지하고 찾지 못하면 중간

JS 알고리즘 7일차 - 버블 정렬 [내부링크]

정렬 알고리즘 소개 정의 정렬 알고리즘은 컬렉션의 항목을 재배열하는 과정을 의미한다. 배워야하는 이유 정렬이 프로그래밍에서 흔하게 사용되기 때문이다. 데이터를 정렬할 수 있는 방법이 많고 각 알고리즘에는 장단점이 존재한다. JavaScript 내장 sort 동작 원리 기본 정렬 순서는 문자열 유니코드, 코드 포인트에 따른다. 배열의 모든 항목이 문자열로 변환되고, 해당 문자열의 유니코드 값이 선택되고 그 다음에 항목이 정렬된다. 내장 정렬 메소드는 선택적 비교 함수를 인자로 전달받는다. 기본적으로 이 함수는 A와 B라는 2개의 항목이 있는 구조로 작성하고 반환되는 값을 토대로 만들 정렬 순서가 결정된다. a - b < 0 때, a를 기준으로 정렬하고 a - b > 0 때, b를 기준으로 정렬한다. 버블 정렬 개요 배열을 가장 작은 숫자에서 가장 큰 숫자순으로 오름차순 정렬할 때 더 큰 숫자가 한 번에 하나씩 뒤로 이동한다. 교환하는 방법 // ES5 function swap(arr,

JS 알고리즘 8일차 - 선택 정렬 [내부링크]

정의 배열을 순회하면서 최솟값을 찾아 앞자리의 요소와 자리를 바꾼다. 의사코드 최솟값을 저장할 변수를 만든다. 처음에는 배열의 시작점이 최솟값에 해당한다. 배열을 순회하면서 수를 비교한다. 만약 저장된 최솟값보다 비교하는 수가 더 작으면 최솟값을 갱신한 뒤 순회를 계속한다. 구현 function selectionSort(arr) { for (let i = 0; i < arr.length < i++) { let lowest = i; for (let j = i+1; j < arr.length; j++) { if (arr[j] < arr[lowest]) { lowest = j; } } if (i !== lowest) { let temp = arr[i]; arr[i] = arr[lowest]; arr[lowest] = temp; } } return arr; } selectionSort([123,32,12,3,4,21,12]); 시간 복잡도 O(n^2)의 시간이 걸린다.

JS 알고리즘 8일차 - 삽입 정렬 [내부링크]

정의 배열의 과반을 점차적으로 만들어 정렬을 구축하며, 과반은 항상 정렬되어 있다. 각 요소를 취하여 정렬되어 있는 절반 속 해당되는 위치에 배치한다. 한 번에 하나의 항목을 올바른 위치에 삽입해서 배열의 정렬된 부분을 점진적으로 구축하는 것 의사코드 배열에서 두 번째 요소를 선택하여 시작한다. 첫 번째 요소를 정렬된 부분으로 간주하기 때문이다. 두 번째 값을 취해서 앞에 있는 값과 비교한다. 필요하다면 위치를 교환한다. 계속 배열을 순회하며 올바른 위치에 있는지 확인한다. 구현 function insertionSort(arr) { for (let i = 1; i < arr.length; i++) { let currentVal = arr[i]; let currentIdx = i; for (let j = i - 1; j >= 0 && arr[j] > currentVal; j--) { arr[j + 1] = arr[j]; currentIdx = j; } arr[currentIdx] =

JS 알고리즘 9일차 - 합병 정렬 [내부링크]

정의 합병과 정렬이라는 두 가지 조합으로 이루어져 있다. 0개 요소, 1개 요소 배열이 이미 정렬되어 있다는 점을 활용한다. 배열을 더 작은 배열로 나누는 방식이다. 더 큰 배열을 나누고 작은 배열을 정렬하는 방식 배열 합병 정렬된 두 배열 합병을 담당할 함수를 먼저 구현한다. 정렬된 두 배열이 주어지면 이 헬퍼 함수는 마찬가지로 정렬된 새 배열을 만든다. O(n+m) 시간과 O(n+m) 공간으로 실행된다. n과 m 이란, 함수에 첫 번째 배열과 두 번째 배열의 크기를 말한다. 의사 코드 빈 배열을 만든다. 입력 두 개를 취하는 함수를 정의하며 마지막에 반환할 빈 배열을 만든다. 각 입력 배열에서 가장 작은 값부터 시작한다. 카운터가 두 개 존재한다. (i, j) while 루프를 사용하면 된다. 아직 살펴보지 않은 값이 있다면 i와 j가 각각의 배열 끝에 도달하지 않았다면, 첫 번째 배열의 값으로 첫 번째 항목을 취한 다음 두 번째 배열의 첫 번째 항목 값과 비교한다. 첫 번째 항

JS 알고리즘 10일차 - 퀵 정렬 [내부링크]

퀵 정렬이란? 기본적으로 데이터를 분할하여 배열에 0개 또는 1개의 항목이 남을 때까지 분할하여 개별적으로 정렬되는 방식이다. 피벗 포인트라 부르는 단일 요소를 선택하여 수행한다. 어떤 배열에서 어떤 요소를 선택하든 사실상 문제가 되지 않는다. 의사코드 배열이 주어지면 요소를 피벗 포인트로 지정하여 배열 속 요소를 재배치하는 함수를 작성한다. 피벗보다 작은 값은 모두 왼쪽으로 이동하며 피벗보다 큰 값을 모두 오른쪽으로 이동한다. 왼쪽과 오른쪽 안에서는 순서가 중요하지 않다. 헬퍼는 제자리에서 수행해야 한다, 새 배열을 만들면 안되고, 피벗 인덱스를 반환해야 한다. 피벗 선정 퀵 정렬의 실행 시간은 피벗 선택 위치에 따라 달라질 수 있다. 이상적으로는 데이터 집합의 중간값이 되도록 선택해야 한다. 하지만 데이터가 무엇인지, 순서가 어떻게 되어 있는지 모른다면 쉽지 않다. 첫 번째요소 혹은 마지막 요소, 중간, 무작위 요소를 선택한다. 첫 번째 요소를 선택하면 시간 복잡도에 영향을 준다

React 프로젝트를 배포한 뒤 새로고침 시 Not found가 뜨는 문제 해결 방법 [내부링크]

문제 React로 만든 프로젝트를 AWS의 Apache에 올린 뒤 웹 페이지에 접속하면 정상적으로 동작을 하였다. 하지만 홈이 아닌 다른 router page에서 새로고침을 하면 Not Found가 뜨는 문제가 발생하였다. 해결 방법 이 문제는 SPA(Single Page Application)에서 흔히 발생하는 문제이고, connect-history-api-fallback 현상이라고도 한다. Vue 프로젝트로 배포했을 때에서 동일한 문제가 발생한 경험이 있다. SPA는 일반적으로 웹 브라우저에서 엑세스 할 수 있는 하나의 색인 파일(index.html)만 사용한다. 그런 다음 HTML5 히스토리를 사용하여 JavaScript를 사용하여 어플리캐이션 탐색을 처리한다. 이로 인해 사용자가 새로고침 버튼을 누르거나 방문 페이지 이외의 페이지에 직접 액세스하거나 뒤로가기를 누르는 등의 행동을 하면 웹 서버가 색인 파일을 무시하여 이 위치에서 파일을 찾을 때 문제가 발생한다. 1단계 : A

합의 [내부링크]

정의 분산 시스템에서 상태를 동기화하기 위해 사용한다. 탈중앙화되었지만, 결정론적으로 운영하기 위해 각자 지켜야하는 규칙 누가 생성한 블록이 유요한지 합의하기 위한 프로토콜 이더리움은 22년 9월 15일 PoW에서 PoS로 전환하는 더 머지 업그레이드가 완료되었다. 작업 증명 (PoW) 임의의 값을 대입하여 얻은 결과 값이 목표 값 이하의 값을 도출할 때까지 해시를 반복하는 작업 해시 함수의 특성에 따라 역산 불가능하여 무작위로 대입하는 작업을 무수히 반복하여야 한다. 마이닝은 새로운 블록을 만들기 위한 작업을 의미하는 것이며, 많은 참가자가 참여할 수록 블록체인의 보안이 강화된다. 마이닝을 통해 새로 발행된 화폐의 보상은 블록체인 시스템 보안에 기여하는 노드에 대한 인센티브이다. 지분 증명 (PoS) 금전적 보증금 예치 기반의 알고리즘 지분 증명 블록체인은 검증인 집합을 유지한다. 이더를 보유한 사람은 이더를 컨트랙트에 예치시키는 특별한 컨트랙트를 보냄으로써 검증인이 된다. 검증인

JS 알고리즘 15일차 - 이중 연결 리스트(push, pop) [내부링크]

이중 연결 리스트란? 인덱스가 없다. 따라서 숫자나 인덱스를 사용해서 무작위 접근을 할 수 없다. 헤드와 테일이 존재한다. 리스트에 있는 모든 노드들은 앞으로 가는 포인터도 있고 뒤로 가는 포인터도 있다. 메모리 사용이 많다. Push 소개 가장 뒤에 요소를 추가한다. 의사코드 값을 가지는 새로운 노드를 만든다. 헤드가 null인지, 혹은 길이가 0인지 확인한다. 만약 리스트가 비어있다면 헤드와 테일 모두가 새로 만든 노드로 설정되어야 한다. 리스트가 비어있지 않다면 현재 테일을 찾아 테일의 next 프로퍼티를 새로운 노드로 설정해줘야 한다. 새로 만든 노드의 prev 프로퍼티를 이전 tail로 설정해준다. tail 프로퍼티를 새로운 노드로 변경해준다. 마지막으로 길이를 1 증가시킨다. 코드 class Node { constructor(val) { this.val = val; this.next = null; this.prev = null; } } class DoublyLinkedLi

JS 알고리즘 15일차 - 이중 연결 리스트(shift, unshift) [내부링크]

Shift 소개 맨 앞에서 노드를 하나 제거한다. 의사코드 리스트가 비어있다면 undefined를 반환한다. 그렇지 않다면 head를 변수에 저장한다. 현재 head를 제거하고 길이를 1 감소시킨다. 만약 길이가 1인 상태에서 제거한다면 head와 tail을 모두 null로 변경한다. 코드 class Node { constructor(val) { this.val = val; this.next = null; this.prev = null; } } class DoublyLinkedList { constructor() { this.head = null; this.tail = null; this.length = 0; } shift() { if (!this.head) return undefined; const oldHead = this.head; if (this.length === 1) { this.head = null this.tail = null } else { this.head = ol

트랜잭션 [내부링크]

1. 트랜잭션의 구조 외부 소유 계정(EOA)에 의해 서명된 메시지 이더리움 네트워크에 전송되고 블록체인에 기록된다. 블록체인 상태 변경을 유발하거나 컨트랙트를 실행하는 유일한 방법이다. 이더리움은 독자적으로 상태가 변경되지 않는다. 컨트랙트는 독자적으로 실행되지 않는다. 논스(nonce) 해당 주소에서 생성한 트랜잭션의 건수 논스값은 0부터 시작하여 트랜잭션을 생성할 때마다 순차적으로 증가한다. 가스 (gas) 가스는 이더리움 네트워크를 사용하기 위한 수수료 이더(ETH)에 대한 사용자 지정 환율(gas price)을 가진 별도의 개념이다. 1 ETH = 10^18 wei 트랜잭션이 사용할 수 있는 자원의 양을 제어하는 데 사용된다. 트랜잭션 수수료의 최댓값 = gasPrice * gasLimit gasPrice: 1가스마다 지급할 가격(wei)을 설정할 수 있다. gasLimit: 최대 가스 단위 수를 지정한다. (이더 전송에 필요한 가스 양은 21000개로 고정되어 있다.) 값

블록체인 암호화 [내부링크]

1. 공개키 암호화 공개키 암호화 == 비대칭 암호화 계산하기는 쉽지만 그 역을 계산하기 어려운 특수한 함수를 바탕으로 생성된 고유한 키를 사용하여 정보를 보호하는 방법 비트코인 및 이더리움에서는 이산 로그 문제를 이용하는 타원곡선 암호화를 활용 2. 개인키와 공개키 개인키(k) 1 ~ 2^256 사이의 무작위로 선택된 숫자 개인키 생성 프로세스는 오프라인 프로세스 대부분의 프로그래밍 언어에 있는 rand 함수 같은 암호학적으로 안전하지 않은 난수 생성기 사용 금지 공개키(K) 타원 곡선에 있는 점(타워 곡선 방정식을 만족하는 x와 y 좌표의 집합) k: 개인키, G: 생성자 점이라 불리는 상수점, K: 공개키, *: 일반 곱셈과 다른 특수한 타원 곡선 곱하기 연산자 이더리움은 secp256k1을 사용한다. 이더리움에서 16진수 문자 130개로 직렬화된 공개키를 확인할 수 있다. 이더리움은 타원 곡선 공개키 접두어 04 (”압축되지 않은 지점”)를 사용한다. 3. 해시 함수 - 주소

블록체인 개요 [내부링크]

블록체인의 등장 : 비트코인 CypherPunk 운동의 산물이다. CypherPunk 운동 : 정부, 거대 기업으로부터 개인의 권리와 자산을 지키기 위한 운동 화폐 권력의 중앙화를 없애기 위해 사토시 나카모토가 발명 발행기관, 운영기관, 중개기관이 없이 인터넷 상에서 다수의 사람들에게 신뢰받는 세계 최초의 탈중앙화 화폐 탄생 블록체인의 진화 : 이더리움 블록체인 2.0이라고도 한다. 이더리움은 스마트 컨트랙트를 실행하는 탈중앙화된 컴퓨팅 인프라로 월드 컴퓨터라고도 불린다. 블록체인에 스마트 컨트랙트 도입하여 DAO(Decentralized Autonomous Organization), 자기주권신원증명, 탈중앙형 금융 등의 가능성을 보여주고 Web3.0의 기틀을 마련했다는 평가를 받는다. 블록체인의 정의 P2P(Peer to Peer) 네트워크를 통해 관리되는 분산 데이터베이스의 한 형태로, 블록체인 노드(네트워크에 연결된 여러 컴퓨터)에 디지털 서명된 서래 정보를 보관하는 분산 원장

JS 알고리즘 14일차 - 단일 연결 리스트(remove, reverse) [내부링크]

Remove 소개 인덱스를 인자로 받아서 해당 인덱스에 있는 노드를 제거하고 주위에 있는 것들을 연결한다. 의사코드 인덱스를 인자로 받는 함수를 정의한다. 인덱스 값이 0보다 작거나 리스트 길이보다 클 경우 undefined를 반환한다. 인덱스가 (리스트의 길이 - 1)와 같을 경우, pop 메소드를 활용해서 마지막 노드를 제거하면 된다. 인덱스가 0일 경우 shift 메소드를 활용해서 첫 번째 노드를 제거하면 된다. 인덱스가 중간에 있는 값이라면 get 메소드를 사용해서 이전 노드의 next를 이전 노드의 next의 next로 설정한다. 마지막으로 리스트 길이를 하나 감소시키고, 제거된 노드를 반환한다. 코드 class Node{ constructor(val) { this.val = val; this.next = null; } } class SinglyLinkedList{ constructor(){ this.head = null; this.tail = null; this.lengt

JS 알고리즘 13일차 - 단일 연결 리스트(get, set) [내부링크]

Get 소개 인덱스 혹은 위치를 의미하는 숫자를 인자로 받아서 주어진 위치에 있는 노드를 반환하는 메소드 의사코드 함수는 입력된 숫자인 인덱스를 인자로 받아야한다. 인덱스 범위에 따라 엣지 케이스가 있을 수 있다. 인덱스가 음수이거나 리스트의 길이보다 같거나 클 경우 동작할 수 없다. 루프를 통해 인덱스가 지정하는 위치에 이를 때까지 반복해서 이동한 다음 해당 인덱스 위치에 있는 노드를 반환한다. 루프 내부에서 next를 반복하기를 권장한다. 매번 루프를 돌 때마다 count 변수를 1 증가시킨다. 코드 class Node{ constructor(val) { this.val = val; this.next = null; } } class SinglyLinkedList{ constructor(){ this.head = null; this.tail = null; this.length = 0; } get(index) { if (index < 0 || index >= this.length)

JS 알고리즘 13일차 - 단일 연결 리스트(insert) [내부링크]

Insert 소개 이미 존재하는 노드를 업데이트하는 대신 주어진 노드를 그곳이 어디든 주어진 위치에 새롭게 삽입한다. 의사코드 인덱스와 값 두 개의 인자를 받아들이는 함수를 정의한다. 범위를 벗어날 경우 삽입이 가능하지 않기 때문에 만일 인덱스가 0보다 작거나 리스트의 길이보다 클 경우 false를 반환한다. 이때 주의할 점은 리스트의 길이보다 크거나 같을 경우가 아니라 클 경우라는 점이다. 인덱스가 길이와 같을 경우는 리스트의 맨 마지막에 삽입하면 되기 때문이다. 즉, 리스트의 맨 마지막에 삽입하기를 원할 경우 다시 작성할 필요없이 push를 활용하면 된다. 마찬가지로 리스트의 맨 앞에 새로운 노드를 삽입하기를 원하면 unshift를 활용할 수 있다. 새롭게 노드를 삽입하려는 위치 바로 전 노드가 어떤 것인지 알게 때문에 이전 노드의 next가 새롭게 생성된 후 삽입되는 노드를 가리키도록 설정한다. 마지막으로 노드를 하나 삽입했기 때문에 길이를 1만큼 증가시키고 true를 반환한다

JS 알고리즘 13일차 - 단일 연결 리스트(shift, unshift) [내부링크]

Shift 개념 현재 헤드가 가리키고 있는 노드를 제거한 후 헤드를 헤드가 가리키도 있던 리스트의 두 번째 노드를 가리키도록 한다. 의사코드 노드가 없을 경우 undefine을 반환한다. 노드가 존재할 경우 현재의 헤드 속성을 변수에 저장하고 현재 헤드의 next 노드를 가리키도록 헤드 속성을 업데이트 한다. 마지막으로 리스트의 길이를 1만큼 감소시키고 제거된 이전 헤드 노드의 값을 반환하다. 코드 class Node{ constructor(val) { this.val = val; this.next = null; } } class SinglyLinkedList{ constructor(){ this.head = null; this.tail = null; this.length = 0; } shift() { if (!this.head) return undefined; let currentHead = this.head; this.head = currentHead.next; this.leng

JavaScript-Proxy 문법 [내부링크]

정의 한 객체에 대한 기본 작업을 가로채고 재정의하는 프록시를 만들 수 있다. Proxy 객체를 사용하면 원래 객체를 대신 사용할 수 있는 객체를 만들지만, 이 객체의 속성 가져오기, 설정 및 정의와 같은 기본 객체 작업을 재정의할 수 있다. 즉, 원본 객체에 접근하기 전에 가로채 요청을 조작할 수 있는 객체 프록시 객체는 일반적으로 속성 액세스를 기록하고, 입력의 유효성을 검사하고, 형식을 지정하거나, 삭제하는데 사용된다. 속성 target : 프록시할 원본(타갯) 객체 handler : 가로채는 작업과 가로채는 작업을 재정의하는 방법을 정의하는 객체이다. 예시 const target = { message1: "hello", message2: "everyone" }; const handler = { get(target, prop) { return 'world'; } }; const proxy = new Proxy(target, handler); console.log(proxy.me

JS 알고리즘 11일차 - 기수 정렬 [내부링크]

기수 정렬 소개 직접 비교를 수행하지 않는 특별한 정렬 알고리즘 방법이다. 다른 방식으로 데이터를 정렬한다. 숫자를 이용한다. 숫자 크기에 대한 정보를 자릿수로 인코딩한다는 사실을 이용한다. 두 수를 비교하지는 않지만 자릿수가 더 많은 수가 더 적은 수보다 크다는 것을 알고 있다. 작동 방식 정렬하려고 하는 수 목록이 있다. 0~9까지 버킷을 만든다. 이러한 버킷은 기수가 10인 한 자리 수로 가능한 모든 숫자를 나타낸다. 각각의 목록의 숫자들의 1의 자리를 기준으로 버킷에 분류한다. 여기 분류된 술서를 유지하면서 다시 목록을 구성한다. 확인된 숫자를 제외하고(1의 자리) 그 다음의 왼쪽 자릿수에서 이 과정을 반복한다. 자릿수가 없는 수는 그 자릿수는 0으로 간주한다. 기수 정렬 Helper 함수 - 1 자릿수 알아내기를 해야한다. 수와 위치를 가져온 다음 그 위치의 숫자를 반환한다. 코드 function getDigit(num, i) { return Math.floor(Math.a

JS 알고리즘 12일차 - 단일 연결 리스트(push, pop) [내부링크]

단일 연결 리스트 소개 정의 문자열, 숫자 등 데이터를 저장하는 자료 구조 Array처럼 순서에 따라 다수의 데이터를 저장한다. 각 노드가 다음 노드로 오직 단일 방향으로만 연결되어있다. Array와 차의점 Array 각 데이터 엘리먼트들은 위치가 지정된다. 즉, 번호에 의해 인덱스(색인)가 부여된다. 연결 리스트 다음 데이터 엘리먼트를 가리키는 인덱스 없이 다수의 데이터 엘리먼트들로 구성된다. 마치 객체들이 연속으로 연결되어 있는 기차와 같다. 인덱스 대신 첫 노드임을 의미하는 변수인 헤드 포인터를 가지고 있다. 새로운 항목을 추가하거나 기존 항목을 제거할 경우 매우 편리하다. 즉, 삽입과 제거를 쉽게 할 수 있다. 용어 노드 : 각각의 엘리먼트를 부르는 이름 연결 리스트들은 다수의 노드들로 구성되고, 각각의 노드는 문자열 혹은 숫자와 같은 하나의 데이터 엘리먼트를 저장한다. 각 노드들은 다음 노드를 가리키는 정보 역시 저장하고 있어야 하며 더 이상 다음 노드가 없을 경우 null