오늘은 어디로 갈까...

사이냅소프트 사원모집 퀴즈 풀이 본문

넋두리

사이냅소프트 사원모집 퀴즈 풀이

剛宇 2009. 4. 28. 07:30
 * 문제 풀이에 중점을 두었기에, 파일입력처리 & 에러처리 & 비~자바적 표현(?)등은 무시해주시기 바랍니다. 그리고 귀찮아서 온통 public static으로 도배하였으니 양해바랍니다. ^^; 이 문제들을 풀면서 가장 어려웠던 점은 역시나~ 변수 이름, 메소드 이름짓기였습니다. ^^;;;
 이 풀이들이 정상적인 풀이인지는 본인도 모릅니다. 샘플 데이터에 대한 결과는 동일한데, 데이터가 달라지면 엉뚱한 결과가 나타날지도 모르니 유의해주시기 바랍니다.
 그리고 좀 더 나은 풀이 방법이나 다른 풀이 방법이 있으면 알려주시면 감사하겠습니다. 다양한 시각을 가지고 싶은 욕망에, 쪽팔림을 무릅쓰고 올린 소스이니, 많은 참여(?) 부탁드립니다. ^^;
 프로그래머는 코드~로 말한다는 이념아래, 설명은 생략하겠습니다. --;

문제 출처 : 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;
				}
			}

		}




Q1. 도형을 찾아라.
 옆에분(?)이 푼거랑 비교를 해보니, 전체적인 개념(?)은 비슷한거 같고 눈에 띄는 한가지. 본인은 끝점을 무식하게 더했는데, 한줄로 표현해주시는 센스~~
	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;
	}
이렇게 다이어트~~ 역시 사람은 배워야하나 ^^;;