728x90

(1) WIL(Weekly I Learned) - 7~8주차

  • 4/9일 항해를 시작한 후 처음으로 프로젝트 진행 기간이 2주인 미니 프로젝트 주차가 시작되었습니다.
  • 팀은 총 4인 백엔드(Spring) 2분(저 포함), 프론트엔드(React) 2분으로 구성되었으며 다시 팀장을 맡게되었습니다.
  • 이전 클론코딩에서의 부족함을 느낀분들을 위해 캐치업 조가 새로 생겨 프로젝트 조, 캐치업 조를 본인이 선택 하여 들어갈 수 있도록 변화가 생겼습니다.

(2) 일정

  • 4/9 - S.A 제출 / 주제 선정 / 와이어프레임 / API설계 / 중간점검 목표 / 2주 진행 계획
  • 4/10 - 튜터 서면 피드백
  • 4/14 - Deer, 알파카 협력사 발표
  • 4/16 - 팀 별 중간체크 / 발제 없음1) WIL(Weekly I Learned) - 7주차
  • 4/22 자정까지 - 결과물 제출
  • 4/23 10:00 ~ 11:00 - 둘러보기
  • 4/23 11:00 - 실전프로젝트 발제

(3) 배운점

  • Web Socket 통신을 이용한 채팅
  • Embedded Redis 사용
  • Spring Security 와 JWT 혼합 사용
  • HtmlEmail객체를 이용한 Email 보내기
    • 비밀번호 찾기를 위해 사용
  • 카카오 소셜로그인
    • 프론트엔드에서 처리 후 카카오에서 받은 Token을 백엔드로 넘겨주어 해당 유저 정보를 DB에 저장 및 JWT 생성 후 프론트엔드로 새로 생성된 Token을 발급

(4) 미니 프로젝트


(5) 느낀점

  • 다들 자신의 주특기에 자신있는 분들을 만나 프로젝트를 순조롭게 진행 할 수 있어 4/16 중간체크 이전 까지 주요 기능인 채팅을 완성할 수 있었습니다.
  • 지금까지 정확한 시간계획 없이 프로젝트 진행, 주특기 공부 등을 하고 있어 정리가 잘 안되는 느낌을 받아 항해 99에서 만난 분들과 시간을 정해 알고리즘 공부를 하기로 하였습니다. 21:30 ~ 23:30 까지 Python 을 이용하여 프로그래머스, 백준 알고리즘 을 풀어 서로 도움되는 시간을 가질 수 있고, 지속적으로 알고리즘을 공부함으로 알고리즘에 익숙해 질 수 있을 것 같습니다.
  • 채팅을 만들며 기본 CRUD를 사용하는 것이 아닌 WebSocket통신을 접할 수 있어 알림, 채팅 등 실시간으로 이루어지는 것에 대해 조금이나마 이해할 수 있었습니다. 아직 Redis에 대해서는 더 공부해야 할 필요성을 느꼇습니다.
  • 처음 WebSocket을 이용하여 채팅을 구현한 것이여서 기분이 매우 좋았으며, 팀원분들과 직접 구현한 채팅 페이지에서 채팅을 하며 소소한 즐거움을 얻을 수 있었습니다.
  • 카카오 소셜로그인은 심화 Spring강의에서 한 프로젝트 안에 백엔드, 프론트엔드가 공존할때에만 구현한 경험이 있어 이를 토대로 소셜로그인을 React와 같이 하려 했지만 Redirect하는 부분에서 Token을 어떻게 넘겨줘야하는지에 문제가 있어 프론트엔드에서 카카오Token을 백엔드로 넘겨주는 방식으로 해결하였습니다. 이게 올바른 방법인지는 아직 해답을 찾이 못하였으나 마지막 코드리뷰때 문의할 예정입니다.
  • 비밀번호 변경하는 방법을 메일보내는 것을 통해 구현하였습니다. 비밀번호 찾기 시 랜덤한 인증번호를 메일과 프론트엔드에 보내어 인증번호를 올바르게 입력하였을때 비밀번호를 변경 할 수 있는 페이지에 나오게 하였는데, 그리 어려운 기능은 아니였지만 Spring boot 코드에서 메일을 보내는 기능을 추가 하여 재밌는 경험이였습니다.

반응형
728x90

(1) 유효성 검사(Validation) 란?

  • 어떤 데이터의 값이 유효한지, 타당한지 확인하는 것을 의미합니다.
  • 보안적인 측면에서 올바르지 않는 데이터가 서버로 전송되거나 DB에 전송되지 않도록 하는 것입니다.

(2) 관련 어노테이션

  • JSR-303 Validator
    • @AssertFalse - 거짓인가?
    • @AssertTrue - 참인가?
    • @Max - 지정 값 이하인가?
    • @Min - 지정 값 이상인가?
    • @DecimalMax - 지정 값 이하 실수인가?
    • @DecimalMin - 지정 값 이상 실수인가?
    • @NotNull - Null이 아닌가?
    • @Null - Null 인가?
    • @Digits (integer=, fraction=) - 대상 수가 지정된 정수, 소수 자리 수 이내인가?
    • @Pattern(regex=,flag=) - 정규식을 만족 하는가?
    • @Future - 미래날짜인가?
    • @Past - 과거 날짜인가?
    • @Size(min=, max=) - 문자열, 배열 등의 크기가 지정크기를 만족 하는가?
  • Hibernate
    • @NotEmpty - Empty 값이 아닌가?
    • @Email - 이메일 형식인가?
    • @URL - URL 형식인가?
    • @Length(min=, max=) - 문자열의 길이가 min과 max 사이인가?
    • @Range(min=, max=) - 숫자 범위가 min과 max 사이인가?

(3) 사용법

  • build.gradle
dependencies {
	compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    
    // https://mvnrepository.com/artifact/org.json/json
    implementation group: 'org.json', name: 'json', version: '20160810'
    
	implementation 'org.springframework.boot:spring-boot-starter-validation:2.3.3.RELEASE'
}
  • DTO
    @NotNull
    @NotBlank(message = "이메일 입력은 필수입니다.")
    @Email(message = "이메일 형식으로 입력해 주세요.")
    private String email;

    @NotNull
    @NotBlank(message = "비밀번호 입력은 필수입니다.")
    private String password;
  • Controller
    //회원 가입
    @PostMapping("/api/user/signup")
    public Object registerUsers(@Valid @RequestBody UserSignupRequestDto userSignupRequestDto){

    }
  • ErrorCode
import lombok.Getter;

public enum ErrorCode {

    NOT_NULL("ERROR_CODE_NOT_NULL","필수값이 누락되었습니다.")
    , MIN_VALUE("ERROR_CODE_MIN_VALUE", "최소값보다 커야 합니다.")
    , PATTERN("ERROR_CODE_PATTERN","값 형식이 다릅니다.")
    , NOT_BLANK("ERROR_CODE_NOT_BLANK","필수값이 누락되었습니다.")
    , EMAIL("ERROR_CODE_EMAIL","이메일 형식이 아닙니다.")
    ;

    @Getter
    private String code;

    @Getter
    private String description;

    ErrorCode(String code, String description) {
        this.code = code;
        this.description = description;
    }
}
  • ErrorResponse
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class ErrorResponse {

    private String code;

    private String description;

    private String errorMessage;

    public ErrorResponse(String code, String description) {
        this.code = code;
        this.description = description;
    }

    public ErrorResponse(String code, String description, String errorMessage) {
        this.code = code;
        this.description = description;
        this.errorMessage = errorMessage;
    }
}
  • ExceptionController
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

@Slf4j
@ControllerAdvice
public class ExceptionController {

    /**
     * @valid  유효성체크에 통과하지 못하면  MethodArgumentNotValidException 이 발생한다.
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> methodValidException(MethodArgumentNotValidException e, HttpServletRequest request){
        log.warn("MethodArgumentNotValidException 발생!!! url:{}, trace:{}",request.getRequestURI(), e.getStackTrace());
        ErrorResponse errorResponse = makeErrorResponse(e.getBindingResult());
        return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
    }

    private ErrorResponse makeErrorResponse(BindingResult bindingResult){
        String code = "";
        String description = "";
        String errorMessage = "";

        //에러가 있다면
        if(bindingResult.hasErrors()){
            //DTO에 설정한 meaasge값을 가져온다
            errorMessage = bindingResult.getFieldError().getDefaultMessage();

            //DTO에 유효성체크를 걸어놓은 어노테이션명을 가져온다.
            String bindResultCode = bindingResult.getFieldError().getCode();

//            switch (bindResultCode){
            switch (Objects.requireNonNull(bindResultCode)){
                case "NotNull":
                    code = ErrorCode.NOT_NULL.getCode();
                    description = ErrorCode.NOT_NULL.getDescription();
                    break;
                case "NotBlank":
                    code = ErrorCode.NOT_BLANK.getCode();
                    description = ErrorCode.NOT_BLANK.getDescription();
                    break;
                case "Min":
                    code = ErrorCode.MIN_VALUE.getCode();
                    description = ErrorCode.MIN_VALUE.getDescription();
                    break;
                case "Pattern":
                    code = ErrorCode.PATTERN.getCode();
                    description = ErrorCode.PATTERN.getDescription();
                    break;
                case "Email":
                    code = ErrorCode.EMAIL.getCode();
                    description = ErrorCode.EMAIL.getDescription();
                    break;
            }
        }

        return new ErrorResponse(code, description, errorMessage);
    }
}

 

  • Controller에서 @Valid 어노테이션이 붙은 값이 넘어왔을때 DTO에서 지정해준 조건에 맞지 않는다면 ExceptionController의 makeErrorResponse 함수가 작동하게 되고, 프론트엔드로 ErrorCode에서 지정해준 값과 DTO에 지정해준 Message가 Response Body에 담겨 프론트엔드로 응답하게 됩니다.

반응형

'Study > Spring' 카테고리의 다른 글

[Spring] QueryDSL-JPA  (0) 2024.12.30
[Spring] @InitBinder  (0) 2021.08.08
[Spring] @Data 어노테이션  (0) 2021.06.30
[Spring] 영속성 컨텍스트 (Persistence Context)  (0) 2021.06.30
[Spring Boot] Spring 프레임워크  (2) 2021.06.26
728x90

(1) 문제

  • 방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.

 


(2) 입력

  • 첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1≤V≤20,000, 1≤E≤300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1≤K≤V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

(3) 출력

  • 첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.

(4) 예제 입력 및 출력


(5) 코드

import heapq
import sys

point_count, line_count = sys.stdin.readline().split()

point_count = int(point_count)
line_count = int(line_count)

start_point = int(sys.stdin.readline())

line_dic = {}

for i in range(point_count):
    line_dic[i + 1] = []

for i in range(line_count):
    u, v, w = sys.stdin.readline().split()
    line_dic[int(u)].append((int(v),int(w)))


def dijkstra(graph, start):
    distances = {node + 1: float('inf') for node in range(point_count)}
    distances[start] = 0
    queue = []
    heapq.heappush(queue, [distances[start], start])
    
    while queue:
        # print(f'distances = {distances}')
        # print(f'queue = {queue}')
        current_distance, current_node = heapq.heappop(queue)
        if distances[current_node] < current_distance:
            continue

        for line in graph[current_node]:
            adjacent = line[0]            
            weight = line[1]
            distance = current_distance + weight
    
            if distance < distances[adjacent]:
                distances[adjacent] = distance
                heapq.heappush(queue, [distance, adjacent])
             
    return distances

distance_dic = dijkstra(line_dic, start_point)

for value in distance_dic.values():
    if value == float('inf'):
        print('INF')
    else:
        print(value)

(6) 실행결과


반응형
728x90

(1) 문제

  • <그림 1>과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여기서 연결되었다는 것은 어떤 집이 좌우, 혹은 아래위로 다른 집이 있는 경우를 말한다. 대각선상에 집이 있는 경우는 연결된 것이 아니다. <그림 2>는 <그림 1>을 단지별로 번호를 붙인 것이다. 지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수를 오름차순으로 정렬하여 출력하는 프로그램을 작성하시오.

 


(2) 입력

  • 첫 번째 줄에는 지도의 크기 N(정사각형이므로 가로와 세로의 크기는 같으며 5≤N≤25)이 입력되고, 그 다음 N줄에는 각각 N개의 자료(0혹은 1)가 입력된다.

(3) 출력

  • 첫 번째 줄에는 총 단지수를 출력하시오. 그리고 각 단지내 집의 수를 오름차순으로 정렬하여 한 줄에 하나씩 출력하시오.

(4) 예제 입력 및 출력


(5) 코드

import sys

def DFS(x,y):
    global count
    if f'{x},{y}' in check_dictionary:
        return count
    else:
        check_dictionary[f'{x},{y}'] = True
        if square_list[x][y] == 1:
            count += 1
            #위
            if y > 0:
                DFS(x,y - 1)
            #아래
            if y < length - 1:
                DFS(x,y + 1)
            #오른쪽
            if x < length - 1:
                DFS(x + 1, y)
            #왼쪽
            if x > 0:
                DFS(x - 1, y)
        
        return count


length = int(sys.stdin.readline())

square_list = []

check_dictionary = {
}

for i in range(length):
    string = sys.stdin.readline().rstrip('\n');
    temp_list = []
    for char in string:
        temp_list.append(int(char))
    square_list.append(temp_list)

count_list = []

for i in range(length):
    for j in range(length):
        count = 0
        count = DFS(i, j)
        if count > 0:
            count_list.append(count)

count_list.sort()
print(len(count_list))
for count in count_list:
    print(count)

(6) 실행결과


반응형
728x90

(1) 문제

  • 수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.
  • 예를 들어, {10, 20, 30, 25, 20}과 {10, 20, 30, 40}, {50, 40, 25, 10} 은 바이토닉 수열이지만,  {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다.
  • 수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.

(2) 입력

첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)

 


(3) 출력

첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.

 


(4) 예제 입력 및 출력


(5) 코드

import sys

length = int(sys.stdin.readline())

sequence_list = list(map(int, sys.stdin.readline().split()))

asc_list = [0] * length
desc_list = [0] * length

for i in range(length):
    for j in range(i):
        if (sequence_list[i] > sequence_list[j] and asc_list[i] < asc_list[j]):
             asc_list[i] = asc_list[j]
    asc_list[i] += 1 

for i in range(length - 1, -1, -1):
    for j in range(length - 1, i, -1):
        if (sequence_list[i] > sequence_list[j] and desc_list[i] < desc_list[j]):
             desc_list[i] = desc_list[j]
    desc_list[i] += 1 

max_count = 0
for i in range(length):
    max_count = max(max_count,asc_list[i] + desc_list[i])

print(max_count - 1)

(6) 실행결과


반응형
728x90

(1) 문제

  • 흑백 영상을 압축하여 표현하는 데이터 구조로 쿼드 트리(Quad Tree)라는 방법이 있다. 흰 점을 나타내는 0과 검은 점을 나타내는 1로만 이루어진 영상(2차원 배열)에서 같은 숫자의 점들이 한 곳에 많이 몰려있으면, 쿼드 트리에서는 이를 압축하여 간단히 표현할 수 있다.
  • 주어진 영상이 모두 0으로만 되어 있으면 압축 결과는 "0"이 되고, 모두 1로만 되어 있으면 압축 결과는 "1"이 된다. 만약 0과 1이 섞여 있으면 전체를 한 번에 나타내지를 못하고, 왼쪽 위, 오른쪽 위, 왼쪽 아래, 오른쪽 아래, 이렇게 4개의 영상으로 나누어 압축하게 되며, 이 4개의 영역을 압축한 결과를 차례대로 괄호 안에 묶어서 표현한다

  • 위 그림에서 왼쪽의 영상은 오른쪽의 배열과 같이 숫자로 주어지며, 이 영상을 쿼드 트리 구조를 이용하여 압축하면 "(0(0011)(0(0111)01)1)"로 표현된다.  N ×N 크기의 영상이 주어질 때, 이 영상을 압축한 결과를 출력하는 프로그램을 작성하시오.

 


(2) 입력

  • 첫째 줄에는 영상의 크기를 나타내는 숫자 N 이 주어진다. N 은 언제나 2의 제곱수로 주어지며, 1 ≤ N ≤ 64의 범위를 가진다. 두 번째 줄부터는 길이 N의 문자열이 N개 들어온다. 각 문자열은 0 또는 1의 숫자로 이루어져 있으며, 영상의 각 점들을 나타낸다.

 


(3) 출력

  • 영상을 압축한 결과를 출력한다.

 


(4) 예제 입력 및 출력


(5) 코드

import sys
import math

square_length = int(sys.stdin.readline())

square_list = []
square_store = []

def DFS(square_arrow_list):
    square = square_arrow_list
    half_size = len(square) // 2

    square_left_up_list = []
    square_rigth_up_list = []
    square_left_down_list = []
    square_right_down_list = []

    for i in range(half_size):
        temp_left_up_list = []
        temp_rigth_up_list = []
        temp_left_down_list = []
        temp_right_down_list = []

        for j in range(half_size):
            # 왼쪽 위
            temp_left_up_list.append(square[i][j])
            # 오른쪽 위
            temp_rigth_up_list.append(square[i][j + half_size])
            # 왼쪽 아래
            temp_left_down_list.append(square[i + half_size][j])
            # 오른쪽 아래
            temp_right_down_list.append(square[i + half_size][j + half_size])

        square_left_up_list.append(temp_left_up_list)
        square_rigth_up_list.append(temp_rigth_up_list)
        square_left_down_list.append(temp_left_down_list)
        square_right_down_list.append(temp_right_down_list)

    print('(', end='')
    is_zero_one(square_store, square_left_up_list)
    is_zero_one(square_store, square_rigth_up_list)
    is_zero_one(square_store, square_left_down_list)
    is_zero_one(square_store, square_right_down_list)
    print(')', end='')


def is_zero_one(square_store, square_arrow_list):
    is_zero = False
    is_one = False
    for row in square_arrow_list:
        if not is_one or not is_zero:
            if 1 in row:
                is_one = True
            if 0 in row:
                is_zero = True
        else:
            break

    if is_one and is_zero:
        DFS(square_arrow_list)
        square_store.append(square_arrow_list)
    elif not is_zero:
        print(1, end='')
    else:
        print(0, end='')

for i in range(square_length):
    string = sys.stdin.readline().rstrip('\n');
    temp_list = []
    for char in string:
        temp_list.append(int(char))
    square_list.append(temp_list)

is_zero_one(square_store, square_list)


(6) 실행결과


반응형
728x90

(1) WIL(Weekly I Learned) - 6주차

  • 4/2일 아쉬웠던 주특기(Spring) 심화가 끝나고 드디어 기다리던 클론코딩 프로젝트가 시작되었습니다.
  • 팀은 총 4인 백엔드(Spring) 2분(저 포함), 프론트엔드(React) 2분으로 구성되었으며 또 다시 팀장을 맡게되었습니다.

(2) 일정

  • 4/2 1차멘토링 전까지 - S.A완료
  • 4/5 ~ 4/6 - 2차 멘토링
  • 4/8 - '쌀 팔다 개발자' 김병욱님 강연
  • 4/8 자정까지 - 클론코딩 결과물 제출
  • 4/9 10:00 ~ 11:00 - 다른조 클론코딩 둘러보기
  • 4/9 11:00 - 미니프로젝트2 발제

(3) 배운점

  • S3를 이용한 이미지 업로드
  • CORS - 타 IP에서 접근을 허용
  • Spring Boot 에서의 JWT 토큰 사용
  • @Valid - 유효성 검사
  • Git - Pull Request
  • Controller 예외처리 및 에러 메세지 보내기

 

 


(4) 클론 코딩


(5) 느낀점

  • 처음으로 백엔드와 프론트엔드로 나누어 프로젝트를 진행하는 경험을 할 수 있었습니다. 혼자만의 속도가 아닌 팀원 전체의 속도에 맞추다보니 완벽하게 프로젝트를 마무리 하지 못하여 아쉬움이 있었지만 그래도 여러사람과의 협업을 통해 프로젝트를 진행 해보았다라는것에 의미가 있었습니다.
  • 매 주차마다 제출하는 단원평가에 코드리뷰, 피드백이 없다 등 아쉬움점을 적어서 인지 스파르타에서 14시~16시에 튜터님이 상시 대기하며 질문 받는 코너가 새로 생겨 프로젝트를 진행 하다 막히는 부분이나 이론상 이해가 안되는 부분이 있으면 물어볼 수 있어 좋았습니다.

반응형
728x90

(1) WIL(Weekly I Learned) - 5주차

  • 3/26일 이전 주특기(Spring)기본을 끝마치고 5주차 주특기(Spring)심화 가 시작되었습니다.
  • 이전과 달리 두분 다 처음보는 분들과 팀원이 되었으며, 랜덤으로 지정된다는 팀장역할을 처음 하게되었습니다.

(2) 일정

  • 3/29 (13:30 ~ 16:30) - 소규모 면담 (신청자 한에서)
  • 3/31 (19:00 ~ 20:00) - 항해톡 (SSL, JWT, index(database), ORM) 크루원 중 신청자 발표
  • 4/1 까지 숙제 완료!
  • 4/2 (~10:00) - 클론 코딩 발제

(3) 배운점

  • Controller
    • Servlet
    • Controller
    • RestController
  • DI
  • Bean
  • IoC
  • 스프링 시큐리티
    • 소셜로그인(카카오)
    • OAuth
  • 테스트 케이스
    • JUnit
    • Mock, Mockito
    • 통합 테스트
  • 영속성

(4) 기본 과제

  • 조건
    • 회원가입
      • 닉네임, 비밀번호 조건에 안맞는경우 에러메세지
    • 로그인 및 검사
    • 소셜로그인
    • 게시글 / 댓글 조회
    • 댓글 작성 / 수정 / 삭제 (로그인 및 자기가 작성한 사용자만)
    • 회원가입 테스트 코드 작성
  • 링크 - loafly.shop/ (현재 닫은 상태)

(5) 느낀점

  • 심화에서는 기본에서 배웠던것에 대한 전체적인 리뷰와 Servlet을사용한 코드, Controller와 RestController를 사용한 코드 등 여러 방법에 대해 배웠습니다.
  • Spring 시큐리티를 이용한 로그인 기능과 소셜로그인 기능을 구성 해 봄으로써 Spring에서 로그인은 기본적으로 도움을 주는 기능들이 있구나 느꼇습니다.
  • 전체적으로 강의 내용이 코드를 전체복사, 붙여넣기 방식으로 진행되어 이해하지 못한부분도 많이 있어 다른강의를 보거나 개인적으로 공부하여 스프링에 대해 더 자세히 알아야 할 필요가 있다고 느꼇습니다.
  • 과제를 해도 코드리뷰, 과제답안 등 피드백이 없어 과제를 잘했는지 잘 못했는지 감을 잡을 수 없어 아쉬움이 있습니다.

반응형
728x90

(1) 문제

  • 요세푸스 문제는 다음과 같다.
  • 1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.
  • N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.

(2) 입력

  • 첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

(3) 출력

  • 예제와 같이 요세푸스 순열을 출력한다.

 


(4) 예제 입력 및 출력


(5) 코드

import sys
N, K = map(int,sys.stdin.readline().split())

player_list = []
for i in range(N):
    player_list.append(i + 1)

cur_index = 0

print('<', end='')
while True:
    cur_index = (cur_index + K - 1) % len(player_list)
    print(player_list.pop(cur_index), end= '')
    if not player_list:
        break
    print(', ',end='')
print('>')

(6) 실행결과


반응형
728x90

(1) 문제

  • 어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 따라서 245는 256의 생성자가 된다. 물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 반대로, 생성자가 여러 개인 자연수도 있을 수 있다.
  • 자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

 


(2) 입력

  • 첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

 


(3) 출력

  • 첫째 줄에 답을 출력한다. 생성자가 없는 경우에는 0을 출력한다.

(4) 예제 입력 및 출력


(5) 코드

import sys
number = int(sys.stdin.readline())

cur_num = 0

while True:
    cur_num += 1
    temp_num = cur_num
    temp_num_sum = 0

    while temp_num != 0:
        temp_num_sum += temp_num % 10
        temp_num = temp_num // 10
        
    temp_num_sum += cur_num
    
    if temp_num_sum == number:
        print(cur_num)
        break
    elif cur_num > number:
        print(0)
        break

(6) 실행결과


반응형

+ Recent posts