카테고리 : 코드,그냥 재미로
2007/09/19 확장된 나선형 배열 출력 문제(Spiral Array)
2007/02/07 나선형 배열 출력 문제 Spiral Array
1st javascript editor의 공짜 사용기한이 얼마 남지 않아서 javascript로 빨리 뭐라도 만들어봐야 겠다는 생각이 들었습니다. 프로젝트 업무 중에는 그런 일이 보이지 않아서 회사의 다른 팀원들이 하고 있는 스터디 모임에서 나왔던 뉴질랜드 화폐문제를 풀어보았습니다.
원래 제가 문제를 봤던 URL : http://rdp.ahamoment.org/wiki/Dollars
뉴질랜드 화폐는 $100, $50, $20, $10, $5 지폐와 $2, $1, 50센트, 20센트, 10센트, 5센트 동전으로 이루어져 있다. 주여진 합계액에 대해서 몇 가지의 방법으로 돈을 구성할 수 있는지 세는 프로그램을 작성해라.
예) 20센트는 4가지 방법으로 만들수 있다. : 1개의 20센트, 2개의 10센트, 10센트+ 2개의 5센트, 4개의 5센트
원래 문제는 파일에서 입력값을 받게 되어 있지만, javascript로 풀다보니 그 부분은 생략했습니다. 직접 풀어보실 분들은 풀이를 나중에 보세요~
<script language="JavaScript" type="text/javascript" src="app/jsUnitCore.js"></script>
<script language="javascript" type="text/javascript">
var unitList = [100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05];
function countWaysOfAmount(totalMoneyAmount, unitIndex, ways){
if (unitIndex == null) unitIndex = 0;
if (ways == null) ways = 0;
var unit = unitList[unitIndex];
var moneyLeft = totalMoneyAmount;
do{
if (moneyLeft == 0) ways++;
else if (unitIndex < unitList.length)
ways = countWaysOfAmount(moneyLeft,unitIndex+1,ways);
moneyLeft = Math.round( (moneyLeft - unit) *100) /100;
} while(moneyLeft >= 0)
return ways;
}
function testDollars(){
assertEquals("0.05", countWaysOfAmount(0.05), 1);
assertEquals("0.1", countWaysOfAmount(0.1 ), 2);
assertEquals("0.15", countWaysOfAmount(0.15), 2);
assertEquals("0.2", countWaysOfAmount(0.2 ), 4);
assertEquals("2", countWaysOfAmount(2), 293);
}
alert(countWaysOfAmount(2));
</script>
코드를 더 다듬을 여지가 있는 것 같지만 일단 올려봅니다 ^^; moneyLeft = Math.round( (moneyLeft - unit) *100) /100; 부분은 다른 언어들과 마찬가지로 javascript에서도 소숫점 계산이 정확하지 않아서 붙인 부분입니다. 이걸 안해주니 5가 나와야하는 값이 4.999999 같이 나오더군요. 이 문제만 아니면 moneyLeft -= unit 으로 간단하게 쓸수 있는데 말이죠 java로 이걸 짠다면 BigDecimal을 쓰거나 별도의 클래스를 정의해야겠죠.
jsunit 없이 로컬에서 수정해 보실 분은 <script language="JavaScript" type="text/javascript" src="app/jsUnitCore.js"></script> 부분과 테스트 메서드만 지우고 돌려 보시면 되겠습니다.
1st javascript editor, jsunit, FireBug 를 한꺼번에 써서 코딩하니 이클립스가 부럽지 않았습니다 ^^; 그리고 jsunit에서 debug("로그"); 로 찍어보는 것도 상당히 유용했구요. 1st javascript edtior나 FireBug가 모두 디버거 기능이 훌륭하지만 반복문의 값을 추적하는 것은 break point 거는 것보다는 로그로 쫙 찍어보는 것이 편하더군요.
# by | 2007/09/19 21:03 | 코드,그냥 재미로 | 트랙백 | 덧글(2)
지난 2월에 회사 워크샵에서 풀었던 나선형 배열 문제에 대한 글을 올린 적이 있었지요. ( http://benelog.egloos.com/901106 )
알고보니 xper.org에도 이 문제가 올라와 있더군요 (http://xper.org/wiki/seminar/SpiralArray). 거기에 가면 다른 분들의 풀이도 많이 볼 수 있습니다. 저는 이 문제를 실컷 가지고 논 후에 더 이상 손 댈 것이 없다고 느껴질때 다른 분들의 풀이를 꼼꼼히 볼 생각입니다.
우연찮게 이에 대한 확장된 문제를 다른 블로그에서 보게 되었습니다. (http://blog.naver.com/itioma?Redirect=Log&logNo=40040118386 ). 그 포스트에서 본 문제에는 아래의 조건들이 더 추가되어 있었습니다.
그리고 숫자는 1에서 시작하고 , 채워지지 않은 부분이 있다면 0으로 표시된다는 점이 제가 처음에 풀었던 문제와 다르네요.
확장된 조건을 다 수용할 수 있는 만족시키는 코드를 다시 한번 만들어보았습니다.
public class MatrixMain {
public static void main(String[] args) {
System.out.println("0.원래의 matrix");
ExtMatrix mp = new ExtMatrix(6,6);
mp.print();System.out.println("1.숫자가 2씩 늘어나게");
mp.setIncrement(2);
mp.print();
System.out.println("2.시작점을 1,1로");
mp.setStartPoint(1, 1);
mp.print();
System.out.println("3.시작방향을 아래부터");
mp.setStartDirection(ExtMatrix.DOWN);
mp.print();System.out.println("4.배열크기 바꾸는건 생성할때 파라미터 바꾸면 됨.");
System.out.println();
System.out.println("5.반시계 반향으로 회전");
mp.setReverseClockWiseTurn();
mp.print();
System.out.println("6.그런 조건 분기 없음.");
System.out.println();
System.out.println("7.한칸씩이 아닌 두칸씩 건너뛰며.");
mp.setMoveStep(2);
mp.print();
}
}
public class ExtMatrix {
public static final int RIGHT = 0;
public static final int DOWN = 1;
public static final int LEFT = 2;
public static final int UP = 3;
private static final int INIT_VALUE = 0;
private static final int CLOCK_WISE_TURN = 1;
private static final int REVERSE_CLOCK_WISE_TURN = -1;
private int m = 0;
private int n = 0;
private int startX = 0;
private int startY = 0;
private int[][] matrix;
private int startDirection = RIGHT;
private int increment = 1;
private int moveStep = 1;
private int turnDirection = CLOCK_WISE_TURN;
public ExtMatrix(int m, int n){
this.m = m;
this.n = n;
matrix = new int[m][n];
}
public void setIncrement(int increment){
this.increment = increment;
}
public void setStartPoint(int startX, int startY){
this.startX = startX;
this.startY = startY;
}
public void setClockWiseTurn(){
turnDirection = CLOCK_WISE_TURN;
}
public void setReverseClockWiseTurn(){
turnDirection = REVERSE_CLOCK_WISE_TURN;
}
public void setMoveStep(int moveStep){
this.moveStep = moveStep;
}
public void setStartDirection(int startDirection){
this.startDirection = startDirection;
}public void print(){
locateNumbers();
for (int i=0;i< m ;i++){
for (int j=0;j<n;j++) System.out.print(matrix[i][j] + "\t");
System.out.println();
}
System.out.println();
}
private void locateNumbers() {
init();
int[] startPosition = new int[]{startX,startY};
matrix[startX][startY]= 1;
int direction = startDirection;
while(move(startPosition ,direction)) direction= getNextDirection(direction);
}
private void init() {
for (int i=0;i< m ;i++){
for (int j=0;j<n;j++) matrix[i][j] = INIT_VALUE;
}
}
private boolean move(int[] position, int direction){
int nowNumber = matrix[position[0]][position[1]];
boolean moved = false;
int[] nextPosition =getNextPosition(position,direction);
while(isMovable(nextPosition[0],nextPosition[1])){
moved = true;
nowNumber+= increment;
position[0] = nextPosition[0];
position[1] = nextPosition[1];
matrix[position[0]][position[1]]= nowNumber;
nextPosition = getNextPosition(position,direction);
}
return moved;
}private int[] getNextPosition(int[] position,int direction){
int x = position[0];
int y = position[1];
if (direction == RIGHT) y+= moveStep;
else if (direction == DOWN) x+= moveStep;
else if (direction == LEFT) y-= moveStep;
else if (direction == UP) x-= moveStep;
return new int[]{x,y};
}
private int getNextDirection(int direction){
direction+= turnDirection;
if (direction<0) direction+=4;
direction = direction %4;
return direction;
}
private boolean isMovable(int x, int y){
if (x>=m) return false;
if (y>=n) return false;
if (x<0) return false;
if (y<0) return false;
if (matrix[x][y]!= INIT_VALUE) return false;
return true;
}
}
방향을 int로 나타내는 것이 처음에는 좋은 아이디어 라고 생각했는데 mp.setStartDirection(ExtMatrix.DOWN); 부분을 보니 타입안전열거형이나 enum을 도입해야지 좀더 코드가 이뻐질 것 같네요.
# by | 2007/09/19 20:36 | 코드,그냥 재미로 | 트랙백 | 덧글(0)
회사 워크샵 갔었을 때 풀었던 문제와 답~
문제:

스스로 풀어보시고 싶으신 분을 위해서 풀이는 조금 공백을 두고 올립니다~
정상혁&이상미 조의 풀이 답입니다.
public class MatrixMain {
public static void main(String[] args) {
Matrix mp = new Matrix(5,5);
mp.locateNumbers();
mp.print();
}
}
public class Matrix {
public static final int RIGHT = 0;
public static final int DOWN = 1;
public static final int LEFT = 2;
public static final int UP = 3;
private static final int INIT_VALUE = -1;
private int m = 0;
private int n = 0;
private int[][] matrix;
public Matrix(int m, int n){
this.m = m;
this.n = n;
matrix = new int[m][n];
}
public void print(){
for (int i=0;i< m ;i++){
for (int j=0;j<n;j++) System.out.print(matrix[i][j] + "\t");
System.out.println();
}
}
public void locateNumbers() {
init();
int[] startPosition = new int[]{0,0};
matrix[0][0]= 0;
int direction = RIGHT;
while(move(startPosition ,direction)) direction ++;
}
private void init() {
for (int i=0;i< m ;i++){
for (int j=0;j<n;j++) matrix[i][j] = INIT_VALUE;
}
}
private boolean move(int[] position, int direction){
int nowNumber = matrix[position[0]][position[1]];
boolean moved = false;
int[] nextPosition =getNextPosition(position,direction);
while(isMovable(nextPosition[0],nextPosition[1])){
moved = true;
nowNumber++;
position[0] = nextPosition[0];
position[1] = nextPosition[1];
matrix[position[0]][position[1]]= nowNumber;
nextPosition = getNextPosition(position,direction);
}
return moved;
}
private int[] getNextPosition(int[] position,int direction){
int x = position[0];
int y = position[1];
int nowDirection = direction%4;
if (nowDirection == RIGHT) y++;
else if (nowDirection == DOWN) x++;
else if (nowDirection == LEFT) y--;
else if (nowDirection == UP) x--;
return new int[]{x,y};
}
private boolean isMovable(int x, int y){
if (x>=m) return false;
if (y>=n) return false;
if (x<0) return false;
if (y<0) return false;
if (matrix[x][y]!= INIT_VALUE) return false;
return true;
}
}
결과:
0 1 2 3 4
15 16 17 18 5
14 23 24 19 6
13 22 21 20 7
12 11 10 9 8
이동하는 좌표를 사이즈가 2인 int배열에다 담았는데, 이걸 따로 클래스로 빼서 만들까 하다가 클래스를 더 늘리기 싫어서 그만뒀습니다 ^^; 소스에서 position[0], position[1]이라고 표시된 부분이 좌표를 나타내는 부분이죠.
main메서드에서 Matrix mp = new Matrix(5,5); 부분이 5*5 행렬을 만든다는 의미입니다.사이즈를 바꿀려면 이 부분을 고치시거나, 사용자 입력에서 온 값을 연결시키면 될 것입니다.
# by | 2007/02/07 22:17 | 코드,그냥 재미로 | 트랙백(1) | 핑백(1) | 덧글(0)
◀ 이전 페이지 다음 페이지 ▶