자료구조(3) 배열과 문자열

9일차 게일 라크만 맥도웰의 코딩 인터뷰 완전 분석 예제 1.4~1.9 내용 정리 9 면접 문제 1.4 회문 순열 주어진 문자열이 회문(palindrome)의 순열인지 아닌지 확인하는 함수를 작성하라. 회문이란 앞으로 읽으나 뒤로 읽으나 같은 단어 혹은 구절을 의미하며, 순열이란 문자열을 재배치하는 것을 뜻한다. 회문이 꼭 사전에 등장하는 단어로 제한될 필요는 없다. 예제 입력 : Tact Coa 출력 : True (순열: “taco cat”, “atco cta” 등) 1 2 3 4 5 6 7 def main(s): arr = list(s) new_arr = set(arr) if 2*len(new_arr) - len(arr) <= 1: return True else: return False 1.5 하나 빼기 문자열을 편집하는 방법에는 세 가지 종류가 있다. 문자 삽입, 문자 삭제, 문자 교체. 문자열 두 개가 주어졌을 때, 문자열을 같게 만들기 위한 편집 횟수가 1회 이내인지 확인하는 함수를 작성하라. ...

2023년 9월 13일 · 3 분 · 배준수

점진적인 개선(5)

책너두 5기 33일차 로버트 C. 마틴의 클린코드 p. 305~ p.321 내용정리 14. 점진적인 개선 지금까지의 리팩터링 결과 인수 유형을 추가하는 것이 매우 쉬워졌다. 이를 확인하기 위해 우선 시스템이 double 인수 유형을 제대로 받아들이는지 확인할 테스트 케이스를 추가한다. 1 2 3 4 5 6 7 public void testSimpleDoublePresent() throws Exception { Args args = new Args("x##", new String[]{"-x", "42.3"}); assertTrue(args.isValid()); assertEquals(1, args.cardinality()); assertTrue(args.has('x')); assertEquals(42.3, args.getDouble('x'), .001); } 스키마 구문분석 코드를 정리하고 ## 감지 코드를 추가한다. ##는 double 인수 유형을 뜻한다. ...

2023년 9월 13일 · 12 분 · 배준수

5. 확률적 분석과 랜덤화된 알고리즘

5. 확률적 분석과 랜덤화된 알고리즘 통계에 관한 기초 용어 설명 확률함수 어떤 사건 X가 일어날 확률을 Pr(X)라고 표현한다. 주사위를 던져서 1이 나오는 사건을 A, 짝수가 나오는 사건을 B라 하면 $$ Pr(A) = \frac16 , \ \ Pr(B) = \frac12 $$ 라고 표현할 수 있다. 기댓값 각 사건이 벌어졌을 때의 이득과 그 사건이 벌어질 확률을 곱한 것을 전체 사건에 대해 합한 값이다. 예를 들어 500원 동전을 던져서 앞면이 나오면 500원을 얻는다고 해보자. 앞면이 나올 확률 X는 2분의 1, 즉 50%이다. 따라서 ...

2023년 9월 12일 · 3 분 · 배준수

메모리 할당 및 사용 구조

책너두 6기 8일차 백은빈, 이성욱의 Real MySQL8.0 1권 p.86 ~ p.97 내용정리 04 아키텍처 4.1.3 메모리 할당 및 사용 구조 글로벌 메모리 영역 : InnoDB 버퍼 풀, MyISAM 키 캐시, 바이너리 로그 버퍼, 리두 로그 버퍼, 테이블 캐시 세션(커넥션) 메모리 영역 : 조인 버퍼, 정렬(sort) 버퍼, 네트워크 버퍼, 리드 버퍼 4.1.3.1 글로벌 메모리 영역 글로벌 메모리 영역의 모든 메모리 공간은 MySQL 서버가 시작되면서 운영체제로부터 할당된다. 클라이언트 스레드의 수와 무관하게 하나의 메모리 공간만 할당되지만 필요에 따라 그 이상도 가능하다. 클라이언트의 스레드 수와 무관하며 생성된 영역이 다수더라도 모든 스레드에 의해 공유된다. ...

2023년 9월 12일 · 8 분 · 배준수

자료구조(1) 해시테이블

8일차 게일 라크만 맥도웰의 코딩 인터뷰 완전 분석 p.133 ~ p. 136, 예제 1.1~1.3 내용 정리 9 면접 문제 01 배열과 문자열 해시테이블 해시테이블(hash table)은 효율적인 탐색을 위한 자료구조 키(key)를 값(value)에 대응시킨다. 연결리스트(linked list)와 해시 코드 함수(hash code function)로 구현할 수 있다. 키와 값을 넣는 과정 키의 해시 코드를 계산한다. 키의 자료형은 보통 int 혹은 long. hash(key) % array_length와 같은 방식으로 해시 코드를 이용해 배열의 인덱스를 구한다. 배열의 각 인덱스에는 키와 값으로 이루어진 연결리스트가 존재한다. 키와 값을 해당 인덱스에 저장한다. 반드시 연결리스트릴 이용한다. 충돌 : 서로 다른 두개의 키가 같은 해시 코드를 가리키거나 서로 다른 두 개의 해시 코드가 같은 인덱스를 가리키는 경우 ...

2023년 9월 12일 · 3 분 · 배준수

점진적인 개선(4)

책너두 5기 32일차 로버트 C. 마틴의 클린코드 p. 296~ p.304 내용정리 14. 점진적인 개선 1차 리팩터링 이후지만 여전히 고쳐야할 부분들이 많이 있다. 첫머리에 나오는 변수, setArgument에 일일이 유형을 확인하는 코드, set 함수들, 오류 처리 코드 등을 개선해야한다. setArgument에서 일일이 유형을 확인하는 코드 => ArgumentMarshaler.set만 호출하면 충분하도록 변경 => setIntArg, setStringArg, setBooleanArg를 해당 ArgumentMarshaler 파생 클래스로 내려야 함 하지만 setIntArg는 args와 currentArgument라는 인스턴스 변수 두 개가 쓰임. setIntarg를 intArgumentMArshaler로 내리려면 둘 다 변수로 내려야 하는데 코드가 지저분해 진다. args 배열을 list로 변환한 후 iterator를 set 함수로 전달하여 해결. ...

2023년 9월 12일 · 1 분 · 배준수

MySQL 서버

책너두 6기 7일차 백은빈, 이성욱의 Real MySQL8.0 1권 p.76 ~ p.85 내용정리 04 아키텍처 MySQL 서버 : 사람의 머리 역할(MySQL 엔진) + 손발 역할(스토리지 엔진)로 구분 스토리지 엔진은 핸들러 API를 만족하면 누구든지 구현해서 MySQL 서버에 추가해서 사용할 수 있음. MySQL 서버에서 기본으로 제공 : InnoDB 스토리지 엔진, MyISAM 스토리지 엔진 4.1 MySQL 엔진 아키텍처 MySQL 서버는 다른 DBMS에 비해 독특하다. 4.1.1 MySQL의 전체 구조 4.1.1.1 MySQL 엔진 클라이언트로부터의 접속 및 쿼리 요청을 처리하는 커넥션 핸들러와 SQL 파서 및 전처리기, 쿼리의 최적화된 실행을 위한 옵티마이저가 중심을 이룬다. ...

2023년 9월 11일 · 3 분 · 배준수

기술적 문제(2) 가능한 최선의 수행 시간

7일차 게일 라크만 맥도웰의 코딩 인터뷰 완전 분석 p.108 ~ p. 130 내용 정리 7. 기술적 문제 가능한 최선의 수행 시간(Best Conceivable Runtime(BCR)) BCR이 무엇일까 생각해 보는 것으로도 문제를 푸는데 유용한 힌트를 발견할 수 있다. 가능한 최선의 수행시간(Best Conceivable Runtime): 상상할 수 있는 모든 해법 중 가장 빠른 알고리즘의 수행 시간을 의미 최선의 경우의 수행 시간(Best Case Runtime): 특정 알고리즘이 가장 빠르게 동작할 경우의 수행 시간을 의미 따라서 둘은 아무 관계가 없다. ...

2023년 9월 11일 · 3 분 · 배준수

점진적인 개선(4)

책너두 5기 31일차 로버트 C. 마틴의 클린코드 p. 288~ p.295 내용정리 14. 점진적인 개선 1차 리팩터링한 결과물은 다음과 같다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 package com.objectmentor.utilities.args; import java.text.ParseException; import java.util.*; public class Args { private String schema; private String[] args; private boolean valid = true; private Set<Character> unexpectedArguments = new TreeSet<Character>(); private Map<Character, ArgumentMarshaler> marshalers = new HashMap<Character, ArgumentMarshaler>(); private Set<Character> argsFound = new HashSet<Character>(); private int currentArgument; private char errorArgumentId = '\0'; private String errorParameter = "TILT"; private ErrorCode errorCode = ErrorCode.OK; private enum ErrorCode { OK, MISSING_STRING, MISSING_INTEGER, INVALID_INTEGER, UNEXPECTED_ARGUMENT } public Args(String schema, String[] args) throws ParseException { this.schema = schema; this.args = args; valid = parse(); } private boolean parse() throws ParseException { if (schema.length() == 0 && args.length == 0) return true; parseSchema(); try { parseArguments(); } catch (ArgsException e) { } return valid; } private boolean parseSchema() throws ParseException { for (String element : schema.split(",")) { if (element.length() > 0) { String trimmedElement = element.trim(); parseSchemaElement(trimmedElement); } } return true; } private void parseSchemaElement(String element) throws ParseException { char elementId = element.charAt(0); String elementTail = element.substring(1); validateSchemaElementId(elementId); if (isBooleanSchemaElement(elementTail)) marshalers.put(elementId, new BooleanArgumentMarshaler()); else if (isStringSchemaElement(elementTail)) marshalers.put(elementId, new StringArgumentMarshaler()); else if (isIntegerSchemaElement(elementTail)) { marshalers.put(elementId, new IntegerArgumentMarshaler()); } else { throw new ParseException(String.format("Argument: %c has invalid format: %s.", elementId, elementTail), 0); } } private void validateSchemaElementId(char elementId) throws ParseException { if (!Character.isLetter(elementId)) { throw new ParseException("Bad character:" + elementId + "in Args format: " + schema, 0); } } private boolean isStringSchemaElement(String elementTail) { return elementTail.equals("*"); } private boolean isBooleanSchemaElement(String elementTail) { return elementTail.length() == 0; } private boolean isIntegerSchemaElement(String elementTail) { return elementTail.equals("#"); } private boolean parseArguments() throws ArgsException { for (currentArgument = 0; currentArgument < args.length; currentArgument++) { String arg = args[currentArgument]; parseArgument(arg); } return true; } private void parseArgument(String arg) throws ArgsException { if (arg.startsWith("-")) parseElements(arg); } private void parseElements(String arg) throws ArgsException { for (int i = 1; i < arg.length(); i++) parseElement(arg.charAt(i)); } private void parseElement(char argChar) throws ArgsException { if (setArgument(argChar)) argsFound.add(argChar); else { unexpectedArguments.add(argChar); errorCode = ErrorCode.UNEXPECTED_ARGUMENT; valid = false; } } private boolean setArgument(char argChar) throws ArgsException { ArgumentMarshaler m = marshalers.get(argChar); try { if (m instanceof BooleanArgumentMarshaler) setBooleanArg(m); else if (m instanceof StringArgumentMarshaler) setStringArg(m); else if (m instanceof IntegerArgumentMarshaler) setIntArg(m); else return false; } catch (ArgsException e) { valid = false; errorArgumentId = argChar; throw e; } return true; } private void setIntArg(ArgumentMarshaler m) throws ArgsException { currentArgument++; String parameter = null; try { parameter = args[currentArgument]; m.set(parameter); } catch (ArrayIndexOutOfBoundsException e) { errorCode = ErrorCode.MISSING_INTEGER; throw new ArgsException(); } catch (ArgsException e) { errorParameter = parameter; errorCode = ErrorCode.INVALID_INTEGER; throw e; } } private void setStringArg(ArgumentMarshaler m) throws ArgsException { currentArgument++; try { m.set(args[currentArgument]); } catch (ArrayIndexOutOfBoundsException e) { errorCode = ErrorCode.MISSING_STRING; throw new ArgsException(); } } private void setBooleanArg(ArgumentMarshaler m) { try { m.set(" true"); } catch (ArgsException e) { } } public int cardinality() { return argsFound.size(); } public String usage() { if (schema.length() > 0) return "-[" + schema + "]"; else return ""; } public String errorMessage() throws Exception { switch (errorCode) { case OK: throw new Exception("TILT: Should not get here."); case UNEXPECTED_ARGUMENT: return unexpectedArgumentMessage(); case MISSING_STRING: return String.format("Could not find string parameter for -%c.", errorArgumentId); case INVALID_INTEGER: return String.format("Argument -%c expects an integer but was '%s'.", errorArgumentId, errorParameter); case MISSING_INTEGER: return String.format("Could not find integer parameter for -%c.", errorArgumentId); } return ""; } private String unexpectedArgumentMessage() { StringBuffer message = new StringBuffer("Argument( s) -"); for (char c : unexpectedArguments) { message.append(c); } message.append("unexpected."); return message.toString(); } public boolean getBoolean(char arg) { Args.ArgumentMarshaler am = marshalers.get(arg); boolean b = false; try { b = am != null && (Boolean) am.get(); } catch (ClassCastException e) { b = false; } return b; } public String getString(char arg) { Args.ArgumentMarshaler am = marshalers.get(arg); try { return am == null ? "" : (String) am.get(); } catch (ClassCastException e) { return ""; } } public int getInt(char arg) { Args.ArgumentMarshaler am = marshalers.get(arg); try { return am == null ? 0 : (Integer) am.get(); } catch (Exception e) { return 0; } } public boolean has(char arg) { return argsFound.contains(arg); } public boolean isValid() { return valid; } private class ArgsException extends Exception { } private abstract class ArgumentMarshaler { public abstract void set(String s) throws ArgsException; public abstract Object get(); } private class BooleanArgumentMarshaler extends ArgumentMarshaler { private boolean booleanValue = false; public void set(String s) { booleanValue = true; } public Object get() { return booleanValue; } } private class StringArgumentMarshaler extends ArgumentMarshaler { private String stringValue = ""; public void set(String s) { stringValue = s; } public Object get() { return stringValue; } } private class IntegerArgumentMarshaler extends ArgumentMarshaler { private int intValue = 0; public void set(String s) throws ArgsException { try { intValue = Integer.parseInt(s); } catch (NumberFormatException e) { throw new ArgsException(); } } public Object get() { return intValue; } } } 읽고나서 솔직히 java를 모르는 나는 이해할 리가 없지만.. 언젠가는.. ...

2023년 9월 11일 · 5 분 · 배준수

권한

책너두 6기 6일차 백은빈, 이성욱의 Real MySQL8.0 1권 p.65 ~ p.75 내용정리 03 사용자 및 권한 3.4 권한(privilege) 글로벌 권한 객체 권한 데이터베이스나 테이블이외의 객체에 적용 데이터베이스나 테이블을 제어하는데 필요 grant명령에서 특정 객체를 명시X 권한을 부여할 떄 반드시 특정 객체 명시 ALL(또는 all privileges) 글로벌과 객체 권한 두 가지 용도로 사용 될 수 있음. 특정 객체에 ALL 권한이 부여되면 해당 객체에 적용될 수 있는 모든 객체 권한을 부여 글로벌로 ALL이 사용되면 글로벌 수준에서 가능한 모든 권한 부여 ...

2023년 9월 9일 · 2 분 · 배준수