Programmers #14

이강용·2023년 4월 27일
0

Programmers

목록 보기
14/58

직사각형 넓이 구하기

📑 문1) 2차원 좌표 평면에 변이 축과 평행한 직사각형이 있습니다. 직사각형 네 꼭짓점의 좌표 [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]가 담겨있는 배열 dots가 매개변수로 주어질 때, 직사각형의 넓이를 return 하도록 solution 함수를 완성해보세요.


제한사항

  • dots의 길이 = 4
  • dots의 원소의 길이 = 2
  • -256 < dots[i]의 원소 < 256
  • 잘못된 입력은 주어지지 않습니다.

입출력 예

dotsresult
[[1, 1], [2, 1], [2, 2], [1, 2]]1
[[-1, -1], [1, 1], [1, -1], [-1, 1]]4

입출력 예 설명

  • 좌표 [[1, 1], [2, 1], [2, 2], [1, 2]] 를 꼭짓점으로 갖는 직사각형의 가로, 세로 길이는 각각 1, 1이므로 직사각형의 넓이는 1 x 1 = 1입니다.
  • 좌표 [[-1, -1], [1, 1], [1, -1], [-1, 1]]를 꼭짓점으로 갖는 직사각형의 가로, 세로 길이는 각각 2, 2이므로 직사각형의 넓이는 2 x 2 = 4입니다.

나의 풀이

package 프로그래머스;

public class RectangleArea {
	
	public static int solution(int[][] dots) {
     
		int minX = dots[0][0];
		int maxX = dots[0][0];
		int minY = dots[0][1];
		int maxY = dots[0][1];
		
		for(int i = 1 ; i < dots.length; i++) {
			if(dots[i][0] < minX) {
				minX = dots[i][0];
			}
			
			if(dots[i][0] > maxX) {
				maxX = dots[i][0];
			}
			
			if(dots[i][1] < minY) {
				minY = dots[i][1];
			}
			
			if(dots[i][1] > maxY) {
				maxY = dots[i][1];
			}
		}
		
        return maxX-minX * maxY-minY;
    }
	
	public static void main(String[] args) {
		int[][] dots = {{-1, -1}, {1, 1}, {1, -1}, {-1, 1}};
		solution(dots);
	}

}

나의 생각

알고리즘 문제를 풀다보면, 어... 이거 당연히 이거 아냐??? 이런 경우가 제법있다... 이번 문제 역시 가로, 세로 길이를 한 번에 알 수 있지만, 이를 어떻게 표현할까.. 나는 제일 먼저 노트를 펴고, 4분면을 그린 뒤 해당 점의 좌표를 찍었다. 점 네 개를 찍다보면 사각형이 그려지는데 만약, 네 개의 점을 무작위로 주어진다면 문제를 어떻게 풀 수 있을까??
내가 생각했던 방법은 x좌표의 최대값최소값의 차이가 x성분의 길이, y좌표의 최대값최소값의 차이가 y성분의 길이라고 생각하였다.
따라서, 사각형의 넓이 : (x최대값 - x최소값) * (y최대값 - y최소값) 으로 나타낼 수 있다.

{-1, -1}, {1, 1}, {1, -1}, {-1, 1} 네 개의 좌표에서 X점, Y점의 최소, 최대는 배열 첫번째 원소의 X, Y의 값을 기준으로 for문을 돌려 최소값보다 작으면 min값을 해당값으로 대체하고, 최대값보다 크면 max값을 해당값으로 대체하여 찾을 수 있다.


캐릭터의 좌표

📑 문2) 머쓱이는 RPG게임을 하고 있습니다. 게임에는 up, down, left, right 방향키가 있으며 각 키를 누르면 위, 아래, 왼쪽, 오른쪽으로 한 칸씩 이동합니다. 예를 들어 [0,0]에서 up을 누른다면 캐릭터의 좌표는 [0, 1], down을 누른다면 [0, -1], left를 누른다면 [-1, 0], right를 누른다면 [1, 0]입니다. 머쓱이가 입력한 방향키의 배열 keyinput와 맵의 크기 board이 매개변수로 주어집니다. 캐릭터는 항상 [0,0]에서 시작할 때 키 입력이 모두 끝난 뒤에 캐릭터의 좌표 [x, y]를 return하도록 solution 함수를 완성해주세요.

  • [0, 0]은 board의 정 중앙에 위치합니다. 예를 들어 board의 가로 크기가 9라면 캐릭터는 왼쪽으로 최대 [-4, 0]까지 오른쪽으로 최대 [4, 0]까지 이동할 수 있습니다.

제한사항

  • board은 [가로 크기, 세로 크기] 형태로 주어집니다.
  • board의 가로 크기와 세로 크기는 홀수입니다.
  • board의 크기를 벗어난 방향키 입력은 무시합니다.
  • 0 ≤ keyinput의 길이 ≤ 50
  • 1 ≤ board[0] ≤ 99
  • 1 ≤ board[1] ≤ 99
  • eyinput은 항상 up, down, left, right만 주어집니다.

입출력 예

keyinputboardresult
["left", "right", "up", "right", "right"][11, 11][2, 1]
["down", "down", "down", "down", "down"][7, 9][0, -4]

입출력 예 설명

  • [0, 0]에서 왼쪽으로 한 칸 오른쪽으로 한 칸 위로 한 칸 오른쪽으로 두 칸 이동한 좌표는 [2, 1]입니다.
  • [0, 0]에서 아래로 다섯 칸 이동한 좌표는 [0, -5]이지만 맵의 세로 크기가 9이므로 아래로는 네 칸을 넘어서 이동할 수 없습니다. 따라서 [0, -4]를 return합니다.

나의 풀이

package 프로그래머스;

import java.util.Arrays;

public class Coordinate {
	
	public static int[] solution(String[] keyinput, int[] board) {
		int[] answer = new int[2];
		int x = 0;
		int y = 0;
      
        for(int i = 0; i < keyinput.length; i++) {
        	if(keyinput[i].equals("up")) {
        		y++;
        
        	}else if(keyinput[i].equals("down")) {
        		y--;
        		
        	}else if (keyinput[i].equals("left")) {
        		x--;
        		
        	}else {
        		x++;
        	}
        	
        	if(x < -(board[0]/2)){
        		x = -(board[0]/2);
        	}else if (x > board[0]/2) {
        		x = board[0]/2;
        	}
        	
        	if(y < -(board[1]/2)) {
        		y = -(board[1]/2);
        	}else if (y > board[1]/2) {
        		y = board[1]/2;
        	}
        }
        answer[0] = x;
        answer[1] = y;
        
        
        return answer;
    }
	
	public static void main(String[] args) {
		
		String[] keyinput = {"down", "down", "down", "down", "down"};
		int[] board = {7,9};
		solution(keyinput, board);
	}

}

나의 생각

의식의 흐름에 따라 문제를 풀었는데, 생각보다 높은 점수를 받게돼서 놀랐다. 처음에는 left, right, up, down을 배열로 담을 생각이였는데, 배열의 좌표를 이용해서 더하는 방법보다 x축, y축 따로 더하는게 더 쉽게 풀 수 있을꺼 같았다. 매개변수 String[] keyinput 을 반복을 돌려 keyinput 배열에 들어 있는 인수를 up, dwon, left, right와 비교하여 x,y 값을 증가 시키는 방법을 사용하였다. 그 외에는 board의 사이즈가 주어지는데, 이 범위를 벗어나게 되면, 범위를 벗어나기 전의 값을 x, y 값에 넣었다.

if(x < -(board[0]/2)){
	x = -(board[0]/2);
}else if (x > board[0]/2) {
	x = board[0]/2;
}
if(y < -(board[1]/2)) {
	y = -(board[1]/2);
}else if (y > board[1]/2) {
	y = board[1]/2;
}

위의 코드를 통해, xy 값을 board의 크기를 기준으로 한 범위 내에서만 움직일 수 있도록 범위를 제한하였다.


좀 더 클린한 코드로 다듬기

변경 전변경 후

종이 자르기

📑 문3) 머쓱이는 큰 종이를 1 x 1 크기로 자르려고 합니다. 예를 들어 2 x 2 크기의 종이를 1 x 1 크기로 자르려면 최소 가위질 세 번이 필요합니다.

정수 M, N이 매개변수로 주어질 때, M x N 크기의 종이를 최소로 가위질 해야하는 횟수를 return 하도록 solution 함수를 완성해보세요.


입출력 예

MNresult
223
259
110

입출력 예 설명

  • 가로 2 세로 5인 종이는 가로로 1번 세로로 8번 총 가위질 9번이 필요합니다.
  • 이미 1 * 1 크기이므로 0을 return 합니다.

나의 풀이

package 프로그래머스;

public class PaperCut {
	public static int solution(int M, int N) {
        return M*N-1;
    }
	
	public static void main(String[] args) {
		solution(2,5);
	}

}

나의 생각

입출력 예를 보는데 보자마자 특정 규칙이 눈에 보였다... M * N - 1,

2 * 2 - 1 = 3
2 * 5 - 1 = 9
1 * 1 - 1 = 0

혹시나 싶어 노트를 펴고 직접 그려보니, 공식이 성립함을 확인할 수 있었다.

이번문제는 쉬어가라는 의미의 문제인것으로 !


로그인 성공?

📑 문4) 머쓱이는 프로그래머스에 로그인하려고 합니다. 머쓱이가 입력한 아이디와 패스워드가 담긴 배열 id_pw와 회원들의 정보가 담긴 2차원 배열 db가 주어질 때, 다음과 같이 로그인 성공, 실패에 따른 메시지를 return하도록 solution 함수를 완성해주세요.

  • 아이디와 비밀번호가 모두 일치하는 회원정보가 있으면 "login"을 return합니다.
  • 로그인이 실패했을 때 아이디가 일치하는 회원이 없다면 “fail”를, 아이디는 일치하지만 비밀번호가 일치하는 회원이 없다면 “wrong pw”를 return 합니다.

제한사항

  • 회원들의 아이디는 문자열입니다.
  • 회원들의 아이디는 알파벳 소문자와 숫자로만 이루어져 있습니다.
  • 회원들의 패스워드는 숫자로 구성된 문자열입니다.
  • 회원들의 비밀번호는 같을 수 있지만 아이디는 같을 수 없습니다.
  • id_pw의 길이는 2입니다.
  • id_pw와 db의 원소는 [아이디, 패스워드] 형태입니다.
  • 1 ≤ 아이디의 길이 ≤ 15
  • 1 ≤ 비밀번호의 길이 ≤ 6
  • 1 ≤ db의 길이 ≤ 10
  • db의 원소의 길이는 2입니다.

입출력 예

id_pwdbresult
["meosseugi", "1234"][["rardss", "123"], ["yyoom", "1234"], ["meosseugi", "1234"]]"login"
["programmer01", "15789"][["programmer02", "111111"], ["programmer00", "134"], ["programmer01", "1145"]]"wrong pw"
["rabbit04", "98761"][["jaja11", "98761"], ["krong0313", "29440"], ["rabbit00", "111333"]]"fail"

입출력 예 설명

  • db에 같은 정보의 계정이 있으므로 "login"을 return합니다.
  • db에 아이디는 같지만 패지스워드가 다른 계정이 있으므로 "wrong pw"를 return합니다.
  • db에 아이디가 맞는 계정이 없으므로 "fail"을 return합니다.

나의 풀이

package 프로그래머스;

public class LoginSucceed {
	
	 public static String solution(String[] id_pw, String[][] db) {
	       
	        for(int i = 0 ; i < db.length; i++) {
        		if(db[i][0].equals(id_pw[0])) {
        			if(db[i][1 ].equals(id_pw[1]) ) { 
        				return "login";
        			}else { 
        				return "wrong pw";
        			}
        		}
	        }
	        return "fail";		
	        	
	        }
	      
	 public static void main(String[] args) {
		 String[] id_pw = {"meosseugi", "0000"};
		 String[][] db = {{"rardss", "123"},{"yyoom", "1234"},{"meosseugi", "1234"}};
		solution(id_pw,db);
	}

}

나의 생각

내가 풀었던 방법을 로직으로 구성해본다면,

  • 아이디가 일치하는가 -> Yes
    • 비밀번호가 일치하는 가 -> Yes
    • -> NO
  • -> NO

먼저, 아이디 일치 여부를 판별 후, 비밀번호가 일치한다면 login, 비밀번호가 일치하지 않으면 wrong pw, 아이디와 비밀번호 모두 일치하지않으면 fail이라는 로직을 구성하였다. id_pw는 배열의 크기가 2로 고정돼 있기때문에 id_pw의 배열의 index값을 직접 지정하여, db배열에 들어 있는 값과 같은지 아닌지를 판별했다.


치킨 쿠폰

📑 문5) 프로그래머스 치킨은 치킨을 시켜먹으면 한 마리당 쿠폰을 한 장 발급합니다. 쿠폰을 열 장 모으면 치킨을 한 마리 서비스로 받을 수 있고, 서비스 치킨에도 쿠폰이 발급됩니다. 시켜먹은 치킨의 수 chicken이 매개변수로 주어질 때 받을 수 있는 최대 서비스 치킨의 수를 return하도록 solution 함수를 완성해주세요.


입출력 예

chickenresult
10011
1,081120

입출력 예 설명

입출력 예 #1

  • 100마리를 주문하면 쿠폰이 100장 발급되므로 서비스 치킨 10마리를 주문할 수 있습니다.
  • 10마리를 주문하면 쿠폰이 10장 발급되므로 서비스 치킨 1마리를 주문할 수 있습니다.
  • 따라서 10 + 1 = 11 을 return합니다.

입출력 예 #2

  • 1081마리를 주문하면 쿠폰이 1081장 발급되므로 서비스 치킨 108마리를 주문할 수 있습니다. 그리고 쿠폰이 1장 남습니다.
  • 108마리를 주문하면 쿠폰이 108장 발급되므로 서비스 치킨 10마리를 주문할 수 있습니다. 그리고 쿠폰이 8장 남습니다.
  • 10마리를 주문하면 쿠폰이 10장 발급되므로 서비스 치킨 1마리를 주문할 수 있습니다.
  • 1마리를 주문하면 쿠폰이 1장 발급됩니다.
  • 가지고 있는 쿠폰이 총 10장이므로 서비스 치킨 1마리를 추가로 주문할 수 있습니다.
  • 따라서 108 + 10 + 1 + 1 = 120 을 return합니다.

나의 풀이

package 프로그래머스;

public class ChickenCoupon {
	public static int solution(int chicken) {
        int answer = 0;
        int coupon = chicken;
        int serviceChicken = 0;
        
        while(coupon >= 10 ) {
        	serviceChicken = coupon / 10;
        	coupon = serviceChicken + coupon % 10;
        	answer +=  serviceChicken;
        }
        return answer;
    }
	
	public static void main(String[] args) {
		solution(1081);
	}

}

나의 생각

내가 생각하는 이 문제의 핵심은 coupon이다. 즉,coupon이 몇 장 있는가에 따라서 서비스 치킨을 받을 수 있다는 의미이다. 그렇기때문에, while문의 조건 역시 coupon의 수가 되어야하고, coupon 10장 = chicken 1마리 이기때문에 coupon이 10보다 크거나 같을때까지 while문의 반복을 수행한다. coupon의 초기값은 매개변수로 주어진chicken의 수와 동일하다. 따라서, 다음과 같은 로직을 구성할 수 있다.

serviceChicken = coupon / 10
coupon = serviceChicken + coupon % 10

  • chicken 이었던 serviceChicken 이었던 결국 coupon이다

  • 1회차 : 치킨 1081마리 , 쿠폰 1081장
  • 2회차 : 서비스 치킨 108마리, 서비스로 받은 쿠폰 108장 , 기존 쿠폰 1장
  • 3회차 : 서비스 치킨 10마리 , 서비스로 받은 쿠폰 10장, 기존 쿠폰 1장+8장
  • 4회차 : 서비스 치킨 1마리 , 서비스로 받은 쿠폰 1장, 기존 쿠폰 9장
  • 5회차 : 서비스 치킨 1마리, 서비스로 받은 쿠폰 1장

    따라서, 최종적으로 서비스로 받은 치킨은 120마리


좀 더 클린하게 작성한 코드

public class ChickenCoupon {
	public static int solution(int chicken) {
     
        int coupon = chicken;
        int serviceChicken = 0;
        
        while(coupon >= 10 ) {
        	serviceChicken += coupon / 10;
        	coupon = coupon / 10 + coupon % 10;	
        }
        
        return serviceChicken;
    }
	
	public static void main(String[] args) {
		solution(1081);
	}

}

기존의 코드에서는 answer 변수는 불필요하게 사용되어 지워지고, 문제에서 원하는 서비스로 받은 치킨의 총 수serviceChicken 변수가 return 값으로 사용되도록 변경

profile
HW + SW = 1

0개의 댓글