Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- DAMO
- date
- ORM
- AES
- PKCS#8
- Instrumentation
- Callable
- 한글조사
- sha1
- Postman
- Runnable
- String
- xlet
- RSA
- 이클립스 플러그인 개발
- IPTV
- Executors
- Executor
- Freemaker
- Java
- 자바
- 암호학
- StringUtils
- JCE
- ACAP
- 한글조사처리
- mac
- PKCS
- Log4J
- 자바 암호화
Archives
- Today
- Total
오늘은 어디로 갈까...
사이냅소프트 사원모집 퀴즈 풀이 본문
* 문제 풀이에 중점을 두었기에, 파일입력처리 & 에러처리 & 비~자바적 표현(?)등은 무시해주시기 바랍니다. 그리고 귀찮아서 온통 public static으로 도배하였으니 양해바랍니다. ^^; 이 문제들을 풀면서 가장 어려웠던 점은 역시나~ 변수 이름, 메소드 이름짓기였습니다. ^^;;;
이 풀이들이 정상적인 풀이인지는 본인도 모릅니다. 샘플 데이터에 대한 결과는 동일한데, 데이터가 달라지면 엉뚱한 결과가 나타날지도 모르니 유의해주시기 바랍니다.
그리고 좀 더 나은 풀이 방법이나 다른 풀이 방법이 있으면 알려주시면 감사하겠습니다. 다양한 시각을 가지고 싶은 욕망에, 쪽팔림을 무릅쓰고 올린 소스이니, 많은 참여(?) 부탁드립니다. ^^;
프로그래머는 코드~로 말한다는 이념아래, 설명은 생략하겠습니다. --;
문제 출처 : http://synap.tistory.com/214
Q1. 도형을 찾아라.
- 도형이 뭔지 몰라서 조금 헤메였던 문제인데, 본인은 해당 점이 속한 줄(level)의 시작 점, 끝점을 계산해낸다음, 각 점들의 상대적인 길이를 추출한후 비교하는식으로 처리하였다. 처음 생각은 시작 점, 끝점을 따로(?) 계산할려고 했으나, 끝점만 구하면 나머지는 자동(?)이라서 한결 편한게 처리했다. 끝점을 구하는방법은 뭐 단순무식하게 더하는것이다. ^^;
- 뭐 나머지는, 입력받은 점들을 정리(?)한다음 각 점들 사이의 길이를 구해서 동일한지 검사하면 되는것이다. 혹시 점들 사이가 직선이 아닐 경우는 에러를 발생시켜 도형이 아니라고 판단하게 하였다.
- 전체 소스
Q2. 문자를 보내자.
- 너무 단순해서 설명할게 없음 ^^;
Q3. 3개의 제곱
- 단순히 주어진 계산식에 의한 값을 비교했을뿐이고~
- 자바에서는 int[] numbers = new int[3]; 선언하면 각 int 값들이 0으로 초기화되므로 0의제곱은 자연스럽게 해결되어버리고, 제곱근은 자바의 Math.sqrt() 함수를 사용했기에, 간단히 해결 ^^;
Q4. 이진수 곱하기.
- 가장 어려웠던 문제가 아닐까 싶다.
- 인간과 컴의 차이에서 오는 곱하기 방법에 대한 고찰(?)을 해보려했으나, 머리가 아파서, 계산하는것처럼 보여주는것으로 결론을 내려버림. 그래서 계산따로~ 결과따로인 프로그램이 되어버렸지만, 결과는 제대로 나오는것 같음 ^^;
Q5. Triples
- 단순히 주어진 계산식에 의한 값을 비교했을뿐이고~
- 어쩌다 for문을 열심히 돌렸을 뿐인데~ 해결된 문제.
Q6. 막대 자르기
- 이 문제를 본 순간 생각나는게 최소공배수, 최대공약수였다. 사실 최소공배수, 최대공약수와 전혀 상관이 없고, 최소공배수, 최대공약수가 뭔지 기억도 안나지만, 왠지 뉘앙스~가 그렇고 그런것 같은 느낌이 들어서 단지~ 나눠(?)봤더니 해결된거 같다. ^^; 나눠진 막대들의 총 합을 구한다음, 가장 큰 막대의 길이로 나눌때 그 나머지가 0일 경우, 나눠진 막대기들이 그 길이에 합체가 가능한지 판단하였다.
Q7. 문장 비교
- 초점은 어디에 두느냐에 따라 풀이과정이 틀려지는 문제인데, 본인은 문자 비교보다는 단어 비교에 중점을 두었다.
- 구분자를 공백(" ")과 마침표(.)로 단어를 추출한 후 비교하였는데, 현재 구현상에서는 구분자도 단어로 인식(?)하는 문제점이 있어서 수정을 해야하지만, 귀찮아서 패스~. ^^;
- 처음는 대용량(?) 처리를 위해 토큰을 나누는 부분을 별도의 클래스로 분리해서 만들려고 했으니, 게으름병이도져서, 메모리상에서 그냥 나눠버림. ^^;
- 넋두리
: 개발자라면 당연히 논리적인 사고능력으로 문제를 해결해야하는데, 불행히도 본인은 그렇게 하지 못한다. 본인은 엉성한 직관력과 실험(?)&관찰(?)로 문제를 해결(쉽게 말해서 찍는다. ^^;)하는데, 아직까지 큰 사고(?)없이 지내온게 신기할따름이다. ^^; 위의 문제들도 대부분 찍어서(?) 푼것들인데, 틀렸다면 어쩔수 없고, 맞았다면 잘 찍은것일뿐이다. ^^; 본인에게 필요한건, 일어날 수 있는 모든수의 테스트 데이터뿐~~~~ ^^;;;;;
: 이자리를 빌어서 재미있는 문제를 던져~주신 사이냅소프트에게 감사의 인사를 ^^
Q6. 막대 자르기 코드에 문제가 있었다. 막대기 합체 로직이 잘못되어서 제대로 계산을 못하는 문제인데, 땜빵으로 수정을 해놨지만, 이것도 정상적으로 작동하리라는 보장이 없으니... 쿨럭... ^^;
기존에는 큰수부터 더해나가서 해당 막대기의 길이에 부합하는지 판단했는데, "큰수" + "큰수 다음의 수" 이렇게 계산이 일어나서, "큰수 다음의 수"가 목적에 부합하지 않을 경우 그 다음의 수부터 계산하는 로직이 빠져있어서, 특정 숫자에서 꽥하는 성질을 발견하여서 수정한것이다. 사실 수정한 코드도 자신이 없는관계로... 누가 한번 정리해주셨으면 감사~감사~ ^^;
- 기존 코드
- 변경 후 코드
Q1. 도형을 찾아라.
옆에분(?)이 푼거랑 비교를 해보니, 전체적인 개념(?)은 비슷한거 같고 눈에 띄는 한가지. 본인은 끝점을 무식하게 더했는데, 한줄로 표현해주시는 센스~~
이 풀이들이 정상적인 풀이인지는 본인도 모릅니다. 샘플 데이터에 대한 결과는 동일한데, 데이터가 달라지면 엉뚱한 결과가 나타날지도 모르니 유의해주시기 바랍니다.
그리고 좀 더 나은 풀이 방법이나 다른 풀이 방법이 있으면 알려주시면 감사하겠습니다. 다양한 시각을 가지고 싶은 욕망에, 쪽팔림을 무릅쓰고 올린 소스이니, 많은 참여(?) 부탁드립니다. ^^;
프로그래머는 코드~로 말한다는 이념아래, 설명은 생략하겠습니다. --;
문제 출처 : http://synap.tistory.com/214
Q1. 도형을 찾아라.
- 도형이 뭔지 몰라서 조금 헤메였던 문제인데, 본인은 해당 점이 속한 줄(level)의 시작 점, 끝점을 계산해낸다음, 각 점들의 상대적인 길이를 추출한후 비교하는식으로 처리하였다. 처음 생각은 시작 점, 끝점을 따로(?) 계산할려고 했으나, 끝점만 구하면 나머지는 자동(?)이라서 한결 편한게 처리했다. 끝점을 구하는방법은 뭐 단순무식하게 더하는것이다. ^^;
/** * <p>해당 라인의 마지막 점 위치를 가져온다.</p> * * @param level * @return */ protected static int getEndPoint(int level) { int k = 0; int n = 0; for (int i = 0; i < level; i++) { k = k + 1; n = n + k; } return n; }- 주어진 조건에서 나올 수 있는 조건은 정삼각형, 평행사변형, 육각형밖에 없는거 같아서, 아래처럼 하드코딩(?)을 하였는데, 점들의 순서만 잘 정리하면 좀 더 이쁘게 구현 할 수 있을거 같았지만, 귀찮아서 패스.
int[] lineLen = new int[numbers.length]; if (numbers.length == 3) { lineLen[0] = getLength(points[0], points[1]); lineLen[1] = getLength(points[1], points[2]); lineLen[2] = getLength(points[2], points[0]); return isSameLength(lineLen); } else if (numbers.length == 4) { if (points[0].level == points[1].level) { lineLen[0] = getLength(points[0], points[1]); lineLen[1] = getLength(points[1], points[3]); lineLen[2] = getLength(points[3], points[2]); lineLen[3] = getLength(points[2], points[1]); return isSameLength(lineLen); } else { lineLen[0] = getLength(points[0], points[2]); lineLen[1] = getLength(points[2], points[3]); lineLen[2] = getLength(points[3], points[1]); lineLen[3] = getLength(points[1], points[0]); return isSameLength(lineLen); } } else if (numbers.length == 6) { if (points[0].level == points[1].level) { lineLen[0] = getLength(points[0], points[1]); lineLen[1] = getLength(points[1], points[3]); lineLen[2] = getLength(points[3], points[5]); lineLen[3] = getLength(points[5], points[4]); lineLen[4] = getLength(points[4], points[2]); lineLen[5] = getLength(points[2], points[0]); return isSameLength(lineLen); } else { return true; } }
- 뭐 나머지는, 입력받은 점들을 정리(?)한다음 각 점들 사이의 길이를 구해서 동일한지 검사하면 되는것이다. 혹시 점들 사이가 직선이 아닐 경우는 에러를 발생시켜 도형이 아니라고 판단하게 하였다.
- 전체 소스
package synap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.StringTokenizer; /** * <p>Q1. 도형을 찾아라.</p> * * @author kangwoo * */ public class Answer1 { public static void main(String[] args) throws Exception { String filename = "q1_input.txt"; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(Answer1.class.getResourceAsStream(filename))); String line = null; while ( (line = reader.readLine()) != null) { int[] numbers = parseNumbers(line); printIsFigure(numbers, System.out); } } finally { if (reader != null) try {reader.close();} catch(IOException ie) {} } } /** * <p>공백으로 분리된 숫자들을 나눠서, 숫자 배열로 변현환한다.</p> * * @param line * @return * @throws NumberFormatException */ public static int[] parseNumbers(String line) throws NumberFormatException { if (line == null || line.trim() == "") { return null; } StringTokenizer st = new StringTokenizer(line.trim(), " "); int[] numbers = new int[st.countTokens()]; for (int i = 0; st.hasMoreTokens(); i++) { numbers[i] = Integer.parseInt(st.nextToken()); } return numbers; } /** * <p>해당 점들로 이루어진 도형이 구성가능한지 판단하여 결과를 출력한다.</p> * * @param numbers 점들 * @param out 출력할 대상 */ public static void printIsFigure(int[] numbers, PrintStream out) { StringBuilder sb = new StringBuilder(); if (numbers != null) { for (int i = 0; i < numbers.length; i++) { if (i > 0) { sb.append(" "); } sb.append(numbers[i]); } } if (isFigure(numbers)) { sb.append(" are the vertices of "); if (numbers.length == 3) { sb.append("a triangle"); } else if (numbers.length == 4) { sb.append("a parallelogram"); } else if (numbers.length == 6) { sb.append("a hexagon"); } } else { sb.append(" are not the vertices of an acceptable figure"); } out.println(sb.toString()); } /** * <p>해당 점들로 이루어진 도형이 구성가능한지 판단한다.</p> * * @param numbers * @return */ public static boolean isFigure(int[] numbers) { if (numbers == null || (numbers.length != 3 && numbers.length != 4 && numbers.length != 6)) { return false; } Point[] points = new Point[numbers.length]; for (int i = 0; i < points.length; i++) { points[i] = getPoint(numbers[i]); } // 정렬 for (int i = 0; i < points.length; i++) { for (int j = 0; j < points.length; j++) { if (points[i].compareTo(points[j]) > 0) { Point temp = points[i]; points[i] = points[j]; points[j] = temp; } } } try { int[] lineLen = new int[numbers.length]; if (numbers.length == 3) { lineLen[0] = getLength(points[0], points[1]); lineLen[1] = getLength(points[1], points[2]); lineLen[2] = getLength(points[2], points[0]); return isSameLength(lineLen); } else if (numbers.length == 4) { if (points[0].level == points[1].level) { lineLen[0] = getLength(points[0], points[1]); lineLen[1] = getLength(points[1], points[3]); lineLen[2] = getLength(points[3], points[2]); lineLen[3] = getLength(points[2], points[1]); return isSameLength(lineLen); } else { lineLen[0] = getLength(points[0], points[2]); lineLen[1] = getLength(points[2], points[3]); lineLen[2] = getLength(points[3], points[1]); lineLen[3] = getLength(points[1], points[0]); return isSameLength(lineLen); } } else if (numbers.length == 6) { if (points[0].level == points[1].level) { lineLen[0] = getLength(points[0], points[1]); lineLen[1] = getLength(points[1], points[3]); lineLen[2] = getLength(points[3], points[5]); lineLen[3] = getLength(points[5], points[4]); lineLen[4] = getLength(points[4], points[2]); lineLen[5] = getLength(points[2], points[0]); return isSameLength(lineLen); } else { return true; } } } catch (IllegalArgumentException e) { return false; } return true; } /** * <p>각 길이들이 동일한 길이인지 검사한다.</p> * * @param lengths 길이들 * @return */ protected static boolean isSameLength(int[] lengths) { if (lengths == null || lengths.length < 2) { return false; } for (int i = 1; i < lengths.length; i++) { if (lengths[0] != lengths[i]) { return false; } } return true; } /** * <p>두 점사이의 위치를 계산한다. 두점사이가 직선이 아닐경우 에러가 발생한다.</p> * * @param x * @param y * @return 두 점으로 이루어진 직선의 길이 * @throws IllegalArgumentException 두점사이가 직선이 아닐경우 발생 */ protected static int getLength(Point x, Point y) { Point tX, tY; if (x.compareTo(y) > 0) { tX = y; tY = x; } else { tX = x; tY = y; } if (tX.level == tY.level) { return tY.currentPoint - tX.currentPoint; } else { int beginDiff = tX.currentPoint - tX.beginPoint; int endDiff = tX.endPoint - tX.currentPoint; if (tY.currentPoint == (tY.endPoint - endDiff) || tY.currentPoint == (tY.beginPoint + beginDiff)) { return tY.level - tX.level; } throw new IllegalArgumentException("입력한 두개의 점(" + x + ", " + y + ")으로는 한 변을 만들 수 없습니다."); } } /** * <p>점의 위치, 해당라인의 시작위치와, 마지막위치, 레벨을 계산한다.</p> * * @param x * @return */ protected static Point getPoint(int x) { int endPoint = 0; for (int i = 1; i < Integer.MAX_VALUE; i++) { endPoint = getEndPoint(i); if (x <= endPoint) { int level = i; int beginPoint = getBeginPoint(level, endPoint); return new Point(level, beginPoint, x, endPoint); } } return null; } protected static int getBeginPoint(int level, int endPoint) { return endPoint - (level - 1); } /** * <p>해당 라인의 마지막 점 위치를 가져온다.</p> * * @param level * @return */ protected static int getEndPoint(int level) { int k = 0; int n = 0; for (int i = 0; i < level; i++) { k = k + 1; n = n + k; } return n; } /** * 점의 위치(해당 레벨의 시작 위치, 끝 위치)를 나타내는 클래스 * @author kangwoo * */ static class Point implements Comparable<Point> { int level; int beginPoint; int currentPoint; int endPoint; Point(int level, int beginPoint, int currentPoint, int endPoint) { this.level = level; this.beginPoint = beginPoint; this.currentPoint = currentPoint; this.endPoint = endPoint; } public int compareTo(Point another) { return currentPoint - another.currentPoint; } @Override public String toString() { return String.valueOf(currentPoint); } } }
Q2. 문자를 보내자.
- 너무 단순해서 설명할게 없음 ^^;
package synap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; /** * <p>Q2. 문자를 보내자.</p> * * @author kangwoo * */ public class Answer2 { private static char[][] keypads = { {'a', 'b', 'c'}, {'d', 'e', 'f'}, {'g', 'h', 'i'}, {'j', 'k', 'l'}, {'m', 'n', 'o'}, {'p', 'q', 'r', 's'}, {'t', 'u', 'v'}, {'w', 'x', 'y', 'z'}, {' '}}; public static void main(String[] args) throws Exception { String filename = "q2_input.txt"; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(Answer2.class.getResourceAsStream(filename))); String line = reader.readLine(); int lineCount = Integer.parseInt(line); String[] lines = new String[lineCount]; for (int i = 0; i < lineCount;i ++) { lines[i] = reader.readLine(); printPressCount(lines[i], i + 1, System.out); } } finally { if (reader != null) try {reader.close();} catch(IOException ie) {} } } /** * <p>해당 문자열를 입력하기 위해 필요한 총 입력 회수를 출력한다.</p> * * @param str 문자열 * @param index Case 순서 * @param out 출력대상 */ public static void printPressCount(String str, int index, PrintStream out) { int count = getPressCount(str); StringBuilder sb = new StringBuilder(); sb.append("Case #").append(index); sb.append(": ").append(count); out.println(sb.toString()); } /** * <p>해당 문자열를 입력하기 위해 필요한 총 입력 회수를 계산한다.</p> * * @param str 문자열 * @return 총 입력 회수 */ public static int getPressCount(String str) { int count = 0; if (str != null) { char[] charArray = str.toCharArray(); for (char c : charArray) { count += getPressCount(c); } } return count; } /** * <p>해당 문자를 입력하기 위해 필요한 입력 회수를 계산한다.</p> * * @param c 문자 * @return 입력 회수 */ public static int getPressCount(char c) { for (int i = keypads.length - 1; i >= 0; i--) { for (int j = 0; j < keypads[i].length; j++) { if (c == keypads[i][j]) { return j + 1; } else if (c < keypads[i][j]) { break; } } } throw new RuntimeException("\"" + c + "\" 문자는 처리할 수 없는 문자입니다."); } }
Q3. 3개의 제곱
- 단순히 주어진 계산식에 의한 값을 비교했을뿐이고~
- 자바에서는 int[] numbers = new int[3]; 선언하면 각 int 값들이 0으로 초기화되므로 0의제곱은 자연스럽게 해결되어버리고, 제곱근은 자바의 Math.sqrt() 함수를 사용했기에, 간단히 해결 ^^;
package synap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * <p>Q3. 3개의 제곱.</p> * * @author kangwoo * */ public class Answer3 { public static void main(String[] args) throws Exception { String filename = "q3_input.txt"; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(Answer3.class.getResourceAsStream(filename))); String line = reader.readLine(); int lineCount = Integer.parseInt(line); String[] lines = new String[lineCount]; for (int i = 0; i < lineCount;i ++) { lines[i] = reader.readLine(); System.out.println(getFermat(Integer.parseInt(lines[i].trim()))); } } finally { if (reader != null) try {reader.close();} catch(IOException ie) {} } } /** * <p>주어진 숫자 k가 3개의 자연수(0을 포함)의 제곱으로 표현될 수 있다면, 그 3개의 수를 출력하고, 불가능하다면 -1을 출력한다.</p> * * @param k 자연수 * @return */ public static String getFermat(int k) { int[] numbers = new int[3]; int remainK = k; for (int i = numbers.length - 1 ; i >= 0; i--) { int square = (int)Math.sqrt(remainK); numbers[i] = square; remainK = remainK - (square * square); } if (remainK > 0) { return "-1"; } else { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { if (i > 0) { sb.append(" "); } sb.append(numbers[i]); } return sb.toString(); } } }
Q4. 이진수 곱하기.
- 가장 어려웠던 문제가 아닐까 싶다.
- 인간과 컴의 차이에서 오는 곱하기 방법에 대한 고찰(?)을 해보려했으나, 머리가 아파서, 계산하는것처럼 보여주는것으로 결론을 내려버림. 그래서 계산따로~ 결과따로인 프로그램이 되어버렸지만, 결과는 제대로 나오는것 같음 ^^;
package synap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * <p>Q4. 이진수 곱하기.</p> * @author kangwoo * */ public class Answer4 { public static void main(String[] args) throws Exception { String filename = "q4_input.txt"; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(Answer4.class.getResourceAsStream(filename))); String line = null; while ( (line = reader.readLine()) != null) { if ("0 0".equals(line.trim())) { break; } String[] binArray = line.split(" "); System.out.println(multiple(binArray[0], binArray[1])); System.out.println(); } } finally { if (reader != null) try {reader.close();} catch(IOException ie) {} } } /** * <p>두 이진수를 곱한다.</p> * @param xStr 이진수 문자열 * @param yStr 이진수 문자열 * @return */ public static String multiple(String xStr, String yStr) { int x = Integer.parseInt(xStr, 2); int y = Integer.parseInt(yStr, 2); int z = x * y; StringBuilder sb = new StringBuilder(); String zStr = Integer.toBinaryString(z); int maxLen = zStr.length(); sb.append(leftPad(Integer.toBinaryString(x), maxLen, " ")).append("\n"); sb.append(leftPad(Integer.toBinaryString(y), maxLen, " ")).append("\n"); sb.append(leftPad(repeat("-", (xStr.length() > yStr.length() ? xStr.length() : yStr.length())), maxLen, " ")).append("\n"); for (int i = 0; i < yStr.length(); i++) { sb.append(leftPad(leftPad(Integer.toBinaryString(x * ((y >> i) & 1)), xStr.length(), "0"), maxLen - i, " ")); for (int j = 0; j < i; j++) { sb.append(" "); } sb.append("\n"); } sb.append(repeat("-", maxLen)).append("\n"); sb.append(zStr); return sb.toString(); } /** * <p>왼쪽부터 크기만큼 문자열로 채워준다.</p> * * @param str * @param size * @param padStr * @return */ public static String leftPad(String str, int size, String padStr) { if (str == null) { return null; } if (padStr == null) { return str; } int strLen = str.length(); int padStrLen = padStr.length(); int padLen = size - strLen; if (padLen <= 0) { return str; } StringBuilder result = new StringBuilder(); if (padLen == padStrLen) { result.append(padStr); result.append(str); } else if (padLen < padStrLen) { result.append(padStr.substring(0, padLen)); result.append(str); } else { char[] padding = padStr.toCharArray(); for (int i = 0; i < padLen; i++) { result.append(padding[ i % padStrLen]); } result.append(str); } return result.toString(); } /** * <p>회수만큼 문자열을 반복시킨다.</p> * * @param str * @param repeat * @return */ public static String repeat(String str, int repeat) { if (str == null) { return null; } if (repeat < 1) { return ""; } int inputLen = str.length(); if (inputLen == 0 || repeat == 1) { return str; } int outputLen = inputLen * repeat; if (inputLen == 1) { char ch = str.charAt(0); char[] output = new char[outputLen]; for (int i = 0; i < outputLen; i++) { output[i] = ch; } return new String(output); } else { StringBuilder output = new StringBuilder(outputLen); for (int i = 0; i < repeat; i++) { output.append(str); } return output.toString(); } } }
Q5. Triples
- 단순히 주어진 계산식에 의한 값을 비교했을뿐이고~
- 어쩌다 for문을 열심히 돌렸을 뿐인데~ 해결된 문제.
package synap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Answer5 { public static void main(String[] args) throws Exception { String filename = "q5_input.txt"; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(Answer5.class.getResourceAsStream(filename))); String line = null; while ( (line = reader.readLine()) != null && !line.trim().equals("0")) { int numCount = Integer.parseInt(line); String[] numberStr = reader.readLine().split(" "); int[] numbers = new int[numCount]; for (int i = 0; i < numCount;i ++) { numbers[i] = Integer.parseInt(numberStr[i]); } System.out.println(getTripleCount(numbers)); } } finally { if (reader != null) try {reader.close();} catch(IOException ie) {} } } /** * <p>Triple 개수룰 가져온다.</p> * * @param numbers * @return */ public static int getTripleCount(int[] numbers) { int count = 0; for (int i = 0; i < numbers.length; i++) { for (int j = i + 1; j < numbers.length; j++) { for (int k = 0; k < numbers.length; k++) { if (i != k && j != k) { if (isTriple(numbers[i], numbers[j], numbers[k])) { count++; } } } } } return count; } /** * <p>x + y = z 인지 판단한다.</p> * * @param x * @param y * @param z * @return */ public static boolean isTriple(int x, int y, int z) { return x + y == z; } }
Q6. 막대 자르기
- 이 문제를 본 순간 생각나는게 최소공배수, 최대공약수였다. 사실 최소공배수, 최대공약수와 전혀 상관이 없고, 최소공배수, 최대공약수가 뭔지 기억도 안나지만, 왠지 뉘앙스~가 그렇고 그런것 같은 느낌이 들어서 단지~ 나눠(?)봤더니 해결된거 같다. ^^; 나눠진 막대들의 총 합을 구한다음, 가장 큰 막대의 길이로 나눌때 그 나머지가 0일 경우, 나눠진 막대기들이 그 길이에 합체가 가능한지 판단하였다.
package synap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; /** * <p>Q6. 막대 자르기</p> * * @author kangwoo * */ public class Answer6 { public static void main(String[] args) throws Exception { String filename = "q6_input.txt"; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(Answer6.class.getResourceAsStream(filename))); String line = null; while ( (line = reader.readLine()) != null && !line.trim().equals("0")) { int numCount = Integer.parseInt(line); String[] numberStr = reader.readLine().split(" "); int[] numbers = new int[numCount]; for (int i = 0; i < numCount;i ++) { numbers[i] = Integer.parseInt(numberStr[i]); } System.out.println(getStickLength(numbers)); } } finally { if (reader != null) try {reader.close();} catch(IOException ie) {} } } public static int getStickLength(int[] divStickLens) { sortDesc(divStickLens); // 내림차순으로 막대길이들을 정렬한다. int maxNum = divStickLens[0]; // 가장 큰 막대길이 int sum = sum(divStickLens); // 막대길이들의 총합 for (int divNum = maxNum; divNum < sum; divNum++) { if (sum % divNum == 0) { if (appendStick(divNum, divStickLens) == 0) { return divNum; } } } return -1; } /** * <p>내림차순으로 숫자들을 정리한다.</p> * * @param numbers */ public static void sortDesc(int[] numbers) { if (numbers != null) { for (int i = 0; i < numbers.length; i++) { for (int j = i + 1; j < numbers.length; j++) { if (numbers[i] < numbers[j]) { int temp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = temp; } } } } } /** * <p>숫자들의 총 합을 구한다.</p> * * @param numbers 숫자들 * @return 합 */ public static int sum(int[] numbers) { int sum = 0; if (numbers != null) { for (int n : numbers) { sum += n; } } return sum; } /** * <p>잘려진 막대들을 붙여서 원래 막대를 만든다.</p> * * @param stickLen 원래 막대의 길이 * @param lenList 잘려진 막대들의 길이들 * @return 남겨진 길이 */ public static int appendStick(int stickLen, int[] divStickLens) { if (stickLen < 1) { throw new IllegalArgumentException("막대의 길이는 0보다 커야합니다."); } if (divStickLens == null || divStickLens.length == 0) { throw new IllegalArgumentException("나눠진 막대의 길이 정보가 존재하지 않습니다."); } List<Integer> stickList = new ArrayList<Integer>(); for (int n : divStickLens) { stickList.add(n); } int remain = 0; while (remain == 0 && stickList.size() > 0) { remain = stickLen; for (int beingIndex = 0; beingIndex < stickList.size() && remain > 0; beingIndex++) { int index = beingIndex; List<Integer> remainList = new ArrayList<Integer>(stickList); while (remain > 0 && index < remainList.size()) { if (remain - remainList.get(index) >= 0) { remain = remain - remainList.remove(index); } else { index++; } } if (remain == 0) { stickList = remainList; } else { remain = stickLen; } } } return remain; } }
Q7. 문장 비교
- 초점은 어디에 두느냐에 따라 풀이과정이 틀려지는 문제인데, 본인은 문자 비교보다는 단어 비교에 중점을 두었다.
- 구분자를 공백(" ")과 마침표(.)로 단어를 추출한 후 비교하였는데, 현재 구현상에서는 구분자도 단어로 인식(?)하는 문제점이 있어서 수정을 해야하지만, 귀찮아서 패스~. ^^;
- 처음는 대용량(?) 처리를 위해 토큰을 나누는 부분을 별도의 클래스로 분리해서 만들려고 했으니, 게으름병이도져서, 메모리상에서 그냥 나눠버림. ^^;
package synap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; public class Answer7 { private static char[] delimiters = {' ', '.'}; public static void main(String[] args) throws Exception { String filename = "q7_input.txt"; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(Answer7.class.getResourceAsStream(filename))); String text1 = reader.readLine(); String text2 = reader.readLine(); printDiffence(text1, text2, System.out); } finally { if (reader != null) try {reader.close();} catch(IOException ie) {} } } /** * <p>두 문장의 차이점을 출력한다.</p> * @param text1 * @param text2 */ private static void printDiffence(String text1, String text2, PrintStream out) { List<String> text1TokenList = getTokenList(text1); List<String> text2TokenList = getTokenList(text2); int text1TokenIndex = 0; int text2TokenIndex = 0; int text1TokenIndexOffset = 0; int text2TokenIndexOffset = 0; while (text1TokenIndex < text1TokenList.size()) { String text1Token = text1TokenList.get(text1TokenIndex); text2TokenIndexOffset = getTokenIndex(text2TokenList, text1Token, text2TokenIndex + text2TokenIndexOffset) - text2TokenIndex; if (text1TokenIndexOffset == text2TokenIndexOffset) { text1TokenIndex++; text2TokenIndex++; } else { int text2TokenIndexOffsetByText1Token = text2TokenIndexOffset; String text2Token = text2TokenList.get(text2TokenIndex); int text1TokenIndexOffsetByText2Token = getTokenIndex(text1TokenList, text2Token, text1TokenIndex + text1TokenIndexOffset) - text1TokenIndex; if (text1TokenIndexOffsetByText2Token < 0 && text2TokenIndexOffsetByText1Token < 0) { // 둘 다 없을 경우 변경된것임. int pos = 0; for (int i = 0; i < text1TokenIndex; i++) { String token = text1TokenList.get(i); pos+= token.length(); } out.println("pos " + pos + " changed " + text1Token.length() + " chars from \"" + text1Token + "\" to \"" + text2Token + "\""); text1TokenIndex++; text2TokenIndex++; } else if (text1TokenIndexOffsetByText2Token < 0) { // text1에 없을 경우 추가된것임 int pos = 0; for (int i = 0; i < text1TokenIndex; i++) { String token = text1TokenList.get(i); pos+= token.length(); } StringBuilder tokensSB = new StringBuilder(); for (int i = text2TokenIndex; i < text2TokenIndex + text2TokenIndexOffsetByText1Token; i++) { String token = text2TokenList.get(i); tokensSB.append(token); } out.println("pos " + pos + " inserted " + tokensSB.length() + " chars \"" + tokensSB.toString() + "\""); text2TokenIndex = text2TokenIndex + text2TokenIndexOffsetByText1Token; } else { // text2에 없을 경우 삭제된검임 StringBuilder tokensSB = new StringBuilder(); int pos = 0; for (int i = 0; i < text1TokenIndex + text1TokenIndexOffsetByText2Token; i++) { String token = text1TokenList.get(i); pos+= token.length(); if (i >= text1TokenIndex) { tokensSB.append(token); } } pos = pos - tokensSB.length(); out.println("pos " + pos + " deleted " + tokensSB.length() + " chars \"" + tokensSB.toString() + "\""); text1TokenIndex = text1TokenIndex + text1TokenIndexOffsetByText2Token; } } text1TokenIndexOffset = 0; text2TokenIndexOffset = 0; } } /** * <p>해당 토큰의 위치를 반환한다.</p> * * @param tokenList * @param token * @param beingIndex * @return */ public static int getTokenIndex(List<String> tokenList, String token, int beingIndex) { for (int i = beingIndex; i < tokenList.size(); i++) { // 대소문자 무시 if (tokenList.get(i).equalsIgnoreCase(token)) { return i; } } return -1; } /** * <p>문자열을 구분자로 나눈다.</p> * @param text * @return */ public static List<String> getTokenList(String text) { List<String> tokenList = new ArrayList<String>(); int textLen = text.length(); int index = 0; int beginIndex = 0; int endIndex = 0; for (index = 0; index < textLen; index++) { if (isDelimiter(text.charAt(index))) { endIndex = index; String token = text.substring(beginIndex, endIndex); if (token.length() > 0) { tokenList.add(token); } beginIndex = endIndex; endIndex = endIndex + 1; token = text.substring(beginIndex, endIndex); tokenList.add(token); beginIndex = endIndex; } } return tokenList; } /** * <p>해당 문자가 구분자인지 판단한다.</p> * * @param c * @return */ public static boolean isDelimiter(char c) { for (char d : delimiters) { if (d == c) { return true; } } return false; } /** * <p>해당 문자열이 구분자인지 판단한다.</p> * * @param str * @return */ public static boolean isDelimiter(String str) { if (str == null) { return false; } if (str.length() == 1) { return isDelimiter(str.charAt(0)); } else { return false; } } }
- 넋두리
: 개발자라면 당연히 논리적인 사고능력으로 문제를 해결해야하는데, 불행히도 본인은 그렇게 하지 못한다. 본인은 엉성한 직관력과 실험(?)&관찰(?)로 문제를 해결(쉽게 말해서 찍는다. ^^;)하는데, 아직까지 큰 사고(?)없이 지내온게 신기할따름이다. ^^; 위의 문제들도 대부분 찍어서(?) 푼것들인데, 틀렸다면 어쩔수 없고, 맞았다면 잘 찍은것일뿐이다. ^^; 본인에게 필요한건, 일어날 수 있는 모든수의 테스트 데이터뿐~~~~ ^^;;;;;
: 이자리를 빌어서 재미있는 문제를 던져~주신 사이냅소프트에게 감사의 인사를 ^^
Q6. 막대 자르기 코드에 문제가 있었다. 막대기 합체 로직이 잘못되어서 제대로 계산을 못하는 문제인데, 땜빵으로 수정을 해놨지만, 이것도 정상적으로 작동하리라는 보장이 없으니... 쿨럭... ^^;
기존에는 큰수부터 더해나가서 해당 막대기의 길이에 부합하는지 판단했는데, "큰수" + "큰수 다음의 수" 이렇게 계산이 일어나서, "큰수 다음의 수"가 목적에 부합하지 않을 경우 그 다음의 수부터 계산하는 로직이 빠져있어서, 특정 숫자에서 꽥하는 성질을 발견하여서 수정한것이다. 사실 수정한 코드도 자신이 없는관계로... 누가 한번 정리해주셨으면 감사~감사~ ^^;
- 기존 코드
int remain = 0; while (remain == 0 && remainList.size() > 0) { remain = stickLen; int index = 0; while (remain > 0 && index < remainList.size()) { if (remain - remainList.get(index) >= 0) { remain = remain - remainList.remove(index); } else { index++; } } }
- 변경 후 코드
int remain = 0; while (remain == 0 && stickList.size() > 0) { remain = stickLen; for (int beingIndex = 0; beingIndex < stickList.size() && remain > 0; beingIndex++) { int index = beingIndex; List<Integer> remainList = new ArrayList<Integer>(stickList); while (remain > 0 && index < remainList.size()) { if (remain - remainList.get(index) >= 0) { remain = remain - remainList.remove(index); } else { index++; } } if (remain == 0) { stickList = remainList; } else { remain = stickLen; } } }
옆에분(?)이 푼거랑 비교를 해보니, 전체적인 개념(?)은 비슷한거 같고 눈에 띄는 한가지. 본인은 끝점을 무식하게 더했는데, 한줄로 표현해주시는 센스~~
protected static int getEndPoint(int level) { int k = 0; int n = 0; for (int i = 0; i < level; i++) { k = k + 1; n = n + k; } return n; }이랬던 놈이~
protected static int getEndPoint(int level) { return level * (level - 1) / 2 + level; }이렇게 다이어트~~ 역시 사람은 배워야하나 ^^;;