반응형

AWS Lambda란

서버리스 컴퓨팅 서비스

서버리스 = 개발자가 서버를 관리할 필요가 없음(클라우드가 서버 관리) -> 코드에만 집중

 

서버리스란?

서버리스 아키텍쳐 = 서버를 직접 관리할 필요가 없는 아키텍처

 

람다의 특징

이벤트 기반으로 즉시 실행 (단일 함수가 간단한 작업을 수행)

이벤트 구독하여 비동기적으로 실행 가능

 

람다의 동작 방식

  1. 이벤트 트리거
  2. 실행 환경 구축
  3. cold start or 활성화 인스턴스 재사용 : 
  4. 함수 코드 실행
  5. 이벤트 처리

함수 호출 -> 새로운 컨테이터 생성 -> (계속 요청) 컨테이너 재사용 -> (5분 요청 끊기면) 컨테이너 초기화

즉 하나의 기능(함수)만 들어있는 컨테이너를 생성

 

Lambda 장점

사용한만큼만 돈을 냄 (비용저럼 하여 절감)

자동 스케일업, 높은 가용성

서버 관리 없이, 코드 개발만 가능

 

Lambda 단점

cold start : 람다가 깰때 최대 지연시간 1s -> 실시간 서비스에 적합하지 않음

서버 제공자에 의존(aws)

긴시간을 소요하는 작업에 불리

코드 재사용이 어려움 / 상태 비저장 : 이벤트로 트리거 될때마다 새로운 환경에서 호출 -> 새로운 컨테이너 띄우는 방식

 

람다 적용에 유리한 서비스

이벤트 기반(트리거)

메시지 큐에 쌓인 메시지 처리 작업

로그 데이터의 실시간 처리

 

Lambda 적용 판단 기준

실행주기 짧은 주기에 적합
하나의 이벤트에 실행 후 인스턴스 소멸
적합
트래픽/부하 이벤트에 응답해 자동으로 확장 적합
비용 구조 실행된 코드에 대한 요금 적용
실행시간/메모리/초당실행횟수/데이터 전송비용/coldstart 발생
확인필요
피크시간/아닌시간
cold start 영향 최초 실행시 지연시간
첫 실행(새 인스턴스 생성)
람다 계속 실행시 재사용 -> 멈추는 경우 발
부적합/확인필요
코드 크기 / 제약사항 함수 크기/실행시간에 제한 적합
자동확장 자동 확장 가능. 중요한 요소인 적합
로그 모니터링 기존과 다름
aws cloudwatch logs로 관리
-
설계 / 개발 경험 기존 개발 프로세스와 다름 -

 

EC2보다 Lambda가 유리한 경우

  • 서비스 특성 (람다:간단한 단일 함수, EC2:특정 인스턴스가 전체 서비스 담당)
  • 트래픽 패턴 (람다:불규칙하고 짧은 실행시간 , EC2:안정적이고 지속적인 트래픽)
  • 리소스 사용 (람다: 함수 사용에 필요한 리소스만 사용 , EC2:지속적으로 설정한 리소스 사용)
  • 비용 (람다:초당 실행시간=>짧은 실행시간&불규칙한 트래픽에 효과 , EC2:일정한 예약, 사용량에 따라 비용 발생)

 

결론

단순한 로직이라 람다에 적합할 것이라 생각

장점 : 서버리스, 자동 스케일업, 비용절감, 이벤트 드리븐 아키

치명적인 cold start 단점: 첫 시작시 1초 지연 가능

 

따라서 비용 구조 / cold start 영향도 확인 필요

 

peak시간 : 자동확장

아닐때 : 비용 최적화(절감)

EC2에 비해 비쌈. 온디맨드 적용시 더 비쌈 -> 하지만 원래 서버는 가용률보다 높게 운영해서, 쓴만큼만 지불 

 

단, peak로 올라갈때 cold start 발생

인스턴스 미리 늘리기 가능 (온디맨드로 인스턴스 수 설정 -> 콜드 스타트 없이 즉시 실행)

 

 

반응형
반응형

자바에서 문자열을 처리하는 방법에는 String, StringBuilder, StringBuffer가 있습니다. 

 

시간이 없다면, 맨 아래로..

한 줄로 정리하자면..

이들은 각각 고정된 문자열, 가변적인 문자열, 스레드 안전한 가변적인 문자열을 처리하는 데 사용됩니다.


1. String

먼저, String 클래스는 불변 객체입니다.

이것은 생성된 문자열이 수정되지 않는다는 것을 의미합니다.

String 클래스는 final 키워드가 지정되어 있기 때문에 하위 클래스에서 재정의 할 수 없습니다.

따라서, String 클래스의 메소드들은 문자열을 수정하는 것이 아니라 새로운 문자열을 생성합니다.

예를 들어, String 클래스의 concat() 메소드는 기존 문자열과 다른 문자열을 연결하여 새로운 문자열을 반환합니다.

 

2. String과 StringBuilder, String Buffer의 차이

반면에 StringBuilder와 StringBuffer 클래스는 가변적인 문자열을 처리합니다.

StringBuilder와 StringBuffer는 둘 다 append()와 insert() 메소드를 제공하여 문자열을 수정할 수 있습니다.

또한, StringBuilder와 StringBuffer는 내부 버퍼를 가지고 있으며, 필요에 따라 버퍼 크기를 조정할 수 있습니다.

 

 

StringBuilder스레드 안전하지 않지만 빠른 속도를 제공합니다.

반면에 StringBuffer스레드 안전하지만 느린 속도를 제공합니다.

 

 

3. 비교 방법이 다른 이유 (내용 vs 주소)

또한, String 클래스와 StringBuilder/StringBuffer 클래스의 문자열 비교 방법도 다릅니다. 

String 클래스에서는 equals() 메소드를 사용하여 문자열을 비교합니다. 

equals() 메소드는 문자열 내용이 같은지를 비교합니다. 

반면에 == 연산자는 두 개의 객체가 같은 객체인지를 비교합니다.

 

즉, == 연산자는 두 개의 문자열이 같은지를 비교하는 것이 아니라, 두 개의 참조(=주소)가 같은지를 비교하는 것입니다.
아래는 String 클래스에서의 == 연산자 예시입니다.

String s1 = "Hello World";
String s2 = "Hello World";
System.out.println(s1 == s2); //true

위 코드에서 s1과 s2는 같은 문자열을 참조하고 있으므로 == 연산자는 true를 반환합니다.

4. StringBuilder 와 StringBuffer 의 차이

StringBuilder 클래스는 StringBuffer와 유사하게 문자열을 가변적으로 조작할 수 있도록 해줍니다. 

 

하지만 StringBuffer는 멀티스레드 환경에서 안전하도록 구현되어 있어서, 동기화 관련 오버헤드가 있습니다. 

그에 반해 StringBuilder는 단일 스레드 환경에서만 사용하도록 고안되어 있어서, 동기화 처리를 하지 않기 때문에 더 빠르게 문자열을 조작할 수 있습니다.

StringBuilder의 메서드는 StringBuffer와 유사하게 구성되어 있어서, 많은 부분이 동일합니다. 

하지만 동기화 처리가 빠진만큼 메서드 수행 시간이 더 빠르고, 더 효율적으로 동작합니다.

 

 

5. 응용!

그럼 내용을 다르게 수정했다가, 다시 원래대로 바꾸면, 참조 값이 다시 같아질까?

public class Test {
    public static void main(String[] args) {
        String s1 = "Hello World";
        String s2 = "Hello World";
		
        System.out.println(s1 == s2); //true
		
        s2 = s2 + "!";
        System.out.println(s1 == s2); //false
		
        s2 = "Hello World";
        System.out.println(s1 == s2); //true
    }
}

첫 번째 System.out.println(s1 == s2)는 s1과 s2가 모두 "Hello World" 문자열을 참조하고 있으므로 true를 출력합니다.

두 번째 System.out.println(s1 == s2)는 s2에 "!"를 추가한 후, s1과 비교하므로 false를 출력합니다. 이는 s2 + "!" 연산이 새로운 String 객체를 생성하고, 그 객체의 참조값을 s2가 가리키게 되기 때문입니다.

세 번째 System.out.println(s1 == s2)는 다시 s2를 "Hello World"로 초기화한 후, s1과 s2가 모두 같은 문자열을 참조하고 있으므로 true를 출력합니다.

 

+ 더 자세한 해설
Java의 String 클래스는 불변(immutable) 객체입니다. 

이는 생성된 String 객체가 변경 불가능하다는 것을 의미합니다. 

즉, 한 번 생성된 String 객체는 그 값을 변경할 수 없습니다.

이러한 불변성은 Java의 메모리 모델에서 매우 중요합니다. 

Java는 객체를 참조하는 변수가 있을 때, 해당 객체에 대한 참조 값을 변수에 저장합니다. 

불변 객체는 생성된 이후에 값이 변경될 수 없기 때문에, 이들의 값은 항상 일정합니다. 

따라서, 불변 객체에 대한 참조를 갖는 변수는 해당 객체가 가리키는 값을 변경할 수 없습니다. 

이러한 특성은 Java의 스레드 안정성(thread-safety)을 보장하는 데에도 도움을 줍니다.

하지만 이러한 불변성 때문에, String 객체를 수정하려고 하면 기존 객체를 변경하는 대신 새로운 객체를 생성합니다. 

예를 들어, String 객체에 대해 문자열 결합 연산자(+)를 사용하면, 기존 객체를 변경하는 대신, 두 개의 String 객체를 연결한 새로운 String 객체를 생성합니다. 

이 때문에 String을 연결하거나 수정하는 작업이 빈번하게 일어날 때, 메모리 소비가 높아질 수 있습니다.

그리고 불변성으로 인해 String 객체가 많은 수로 생성될 수 있다는 단점도 있습니다. 예를 들어, 문자열을 많이 연결하는 작업을 수행할 경우 새로운 String 객체가 생성될 수 있기 때문에 메모리 사용량이 늘어날 수 있습니다. 이러한 경우에는 StringBuilder나 StringBuffer 클래스를 사용하는 것이 더 효율적입니다. 이 클래스들은 가변(mutable) 객체로, 문자열을 연결할 때 기존 객체를 변경하는 대신에 내부적으로 저장공간을 조정하여 문자열을 추가할 수 있도록 해줍니다.

 

 

6. 총정리

그래서 언제 사용하는게 좋을까?!

String : 값이 자주 변하지 않을 때 (자주 변하면, 메모리 소비가 심함)

StringBuilder : 값이 변하고, 싱글스레드일때 (대신 빠름)

StringBuffer : 값이 변하고, 멀티스레드일때 (대신 느림)

 

 


이상으로, Java에서 문자열을 다루는 String, StringBuffer, StringBuilder 클래스에 대해 알아보았습니다. 

적절한 상황에서 각 클래스를 적절히 사용하면서, 보다 효율적으로 문자열을 다룰 수 있을 것입니다.

반응형
반응형

오늘은 이클립스와 스프링 기반의 프로젝트에 스웨거를 적용하는 방법에 대해 적어보려 합니다.


전체 프로세스

  1. Pom.xml 에 의존성 추가(swagger 라이브러리)
  2. SwaggerConfig.java 생성 (Swagger 관련 설정 담당)
  3. Dispatcher-Servlet.xml 수정 (Bean 등록 추가)
  4. Controller 단 수정  (Swagger관련 어노테이션 추가)
  5. Swagger UI 확인

 
하나씩 자세히 알아보겠습니다


Pom.xml 에 의존성 추가(swagger 라이브러리)

pom에 관련 라이브러리 2개를 추가합니다.
버전은 2.9.2를 기준으로 작성할게요.
(3.0.0 부터는 상세 설정이 조금씩 달라지니까, 다른 글을 확인 해보세요) 
아래를 복사해서 사용하시면 됩니다.

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

SwaggerConfig.java 생성 (Swagger 관련 설정 담당)

Swagger 관련 설정을 정의할건데, 적당한 위치에 아래 파일을 만들어주세요

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.example.controller"))
            .paths(PathSelectors.any())
            .build()
            .apiInfo(apiInfo());
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("Your API Title")
            .description("Your API Description")
            .version("1.0.0")
            .build();
    }
}

위의 Docket은 Swagger 문서를 구성하는 데 사용되는 핵심 구성 요소 중 하나입니다. 이 설정은 Swagger가 문서화 할 API의 내용과 대상 패키지를 지정합니다.
DocumentationType.SWAGGER_2: Swagger 버전을 지정합니다.
select(): 문서화 할 API를 선택합니다.
apis(RequestHandlerSelectors.basePackage("com.example.controller")): 문서화 할 API가 포함 된 패키지를 선택합니다. 해당 패키지 내에 있는 모든 클래스가 문서화 대상이 됩니다.
paths(PathSelectors.any()): 문서화 대상 API의 URL을 선택합니다. PathSelectors.any()를 사용하면 모든 URL이 대상이 됩니다. 이것은 대부분의 경우에 유용합니다.
build(): Docket 객체를 생성합니다.

이 설정을 통해 Swagger는"com.example.controller" 패키지에 있는 모든 API를 문서화하고, 모든 URL을 대상으로 문서를 생성합니다. 
이를 통해 Swagger UI를 사용하여 문서화 된 API를 쉽게 찾을 수 있습니다.
 
아래의 apiInfo()는 Swagger UI 페이지에 출력될 API 소개 내용에 대한 설정입니다.
일단 이렇게 설정해서 화면을 만들고, 원하는 문구로 수정하시면 됩니다


Dispatcher-Servlet.xml 수정 (Bean 등록 추가)

bean의 class 속성에는 SwaggerConfig.java 파일에 속한 패키지를 적어주시면 됩니다

 <!-- swagger -->
<bean id="swagger2Config" class="com.example.config.SwaggerConfig"></bean>
<mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"></mvc:resources>
<mvc:resources location="classpath:/META-INF/resources/webjars/"  mapping="/webjars/**"></mvc:resources>

SwaggerConfig 클래스를 swagger2Config 빈으로 등록합니다. SwaggerConfig 클래스는 Swagger 설정을 담당합니다.

mvc:resources를 사용하여 Swagger UI에서 사용할 정적 리소스를 등록합니다. 
location 속성은 Swagger UI 리소스가 위치한 경로를 지정하고, mapping 속성은 해당 리소스를 사용할 URL 패턴을 설정합니다.
 
첫 번째 mvc:resources 요소에서는 swagger-ui.html 파일에 대한 매핑을 설정합니다. Swagger UI는 이 HTML 파일을 통해 브라우저에서 Swagger UI를 표시합니다.

두 번째 mvc:resources 요소에서는 webjars 디렉토리 내에 있는 정적 리소스에 대한 매핑을 설정합니다. 이 디렉토리에는 Swagger UI에서 사용되는 JavaScript, CSS, 이미지 등의 파일이 포함되어 있습니다. /webjars/** URL 패턴은 모든 webjars 디렉토리 내의 파일에 대해 매핑됩니다.


Controller 단 수정  (Swagger관련 어노테이션 추가)

@RestController
@RequestMapping("/test")
@Api(value = "Example API List", tags = "Example API")
public class ExampleController {

    @ApiOperation(value = "id로 결과를 조회합니다", notes = "Returns an example by their ID")
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "성공"),
        @ApiResponse(code = 404, message = "오류")
    })
    @GetMapping("/examples/{id}")
    public Example getExampleById(@PathVariable Long id) {
        // 기존 Controller 로직
    }
    
}

새롭게 작성이라면 이런식으로 작성을 하시면 되고
추가를 하게 된다면 @Api로 시작 되는 어노테이션을 프로젝트와 기능에 맞게 작성해서 추가해주시면 됩니다.
@ApiOperation 어노테이션을 사용하여 각 엔드포인트에 대한 설명과 메서드를 지정합니다. 
@ApiResponses 어노테이션을 사용하여 각 응답 코드에 대한 설명과 메시지를 지정합니다.
 
 
마지막으로 테스트는
http://localhost:8080/swagger-ui.html 에 접속해서 UI를 확인합니다.
만약 prefix (context-path)등이 있다면8080 뒤에 /{prefix}를 넣어서 입력해주세요
 
 
ㄲㅡㅌ

반응형
반응형

지난달 신시계 그룹의 신세계아이앤씨에서 개발/운영 업무를 뽑는 공고가 있어서 지원했고,
경력기술서와 경험이 마음에 드셨는지 서류전형에 통과했고, 코딩테스트를 보았습니다.


채용 절차는 서류전형 - 코딩테스트 -1차면접 - 2차면접 순으로 진행되었으며, 코딩테스트 후 3일후에 합격통보와 면접 제의를 받았습니다. 다른 분들은 2~3주까지도 걸린다고 했는데, 이번엔 결과가 빨리 나온 편인것 같습니다.

서류 전형

다른 대기업들과 비슷한 채용 사이트(career)를 사용하며, 구성도 거의 비슷해서 특별한 건 없었습니다.
기본정보 / 학력,자격증 / 경력 / 경력기술서 등등 작성하며, 퇴직 사유가 그나마 생각하기에 오래 걸리는 문항이었습니다

마지막 페이지는 자기소개서로 크게 3가지 질문이었습니다. 지원동기, 차별화된 능력과 경험, 자유양식(어필) 이렇게 구성되어 있었던것 같아요

코딩테스트

코딩테스트는 정해진 시간에 접속해서 풀었던것 같아요
사이트 : TestDome
특징 : 모든 지문이 영어
구성 : 10문제 (SQL 7문제 / Java 3문제)
방식 : 1문제당 제한시간내에 풀어서 제출하며, 한번 넘어가면 돌아올 수 없음
난이도 : 쉬움 (SQL도 경력에서 DB를 다뤘다면, 시간이 넉넉하고, JAVA 문제는 프로그래머스 1~1.5?)
특징 : 시간과의 싸움 (시간이 빠듯하다는 평이 많음)
특징2 : JAVA문제는 DFS, DP, 그리디 이런 알고리즘이 아니라 객체지향 관점에서 JAVA를 활용하는 방식에 대한 문제

후기

10문제중 9문제 풀었고, 1문제는 특정 케이스에 실패했는데. 운이 좋게 합격했네요
테스트 3일 후에 합격통보와 면접 일정에 관련된 안내를 받았습니다.
참고로 1차면접은 화상 면접이라고 하네요

반응형
반응형

최근 현대 오토에버의 개발/운영 업무를 뽑는 공고가 있어서 지원했고, 서류 접수후에 인적성검사와 코딩테스트를 보았습니다.

 

채용 절차는 서류전형 - 인적성검사 & 코딩테스트 -1차면접 - 2차면접 순으로 진행됩니다.

반응형

서류 전형

다른 대기업들과 비슷한 채용 사이트(career)를 사용하며, 구성도 거의 비슷해서 특별한 건 없었습니다.

기본정보 / 학력,자격증 / 경력 / 경력기술서 등등 작성하며, 퇴직 사유가 그나마 생각하기에 오래 걸리는 문항이었습니다

 

마지막 페이지는 자기소개서로 크게 3가지 질문이었습니다. 지원동기, 희망업무를 강점을 근거로 기술, 역량기술서 이렇게 구성되어 있었던것 같아요

인적성검사(HMAT)

서류 전형을 통과하면, 인사팀에서 메일로 인적성검사를 보는 링크와 시험 가능한 기한을 알려줍니다.

인적성검사를 HMAT이라고 부르는것 같아요

구성 : 336문제에 60분정도

특징 : lpsative(=1 set에 3질문이 있고, 각 질문당 점수를 메기며, 그 중에 가장 멀고/가까운 답을 구하는 형식)

현대는 hmat의 기준이 높은 편으로 50%까지도 해당 검사로 필터링한다는 얘기가 있는 만큼 까다로운 편인것 같아요.

또한, 결과를 바탕으로 면접에서 질문이 들어오기도 한다고 합니다.

그렇기 때문에 답을 솔직하고 일관성있게 풀어야합니다.

(거짓말을 걸러내기 위한 장치들이 많이 있다고 해요)

코딩테스트(softeer)

코딩테스트는 정해진 기한내에 아무때나 접속해서 풀었어요

사이트 : softeer (현대차 그룹의 개발 직군을 위한 플랫폼 : https://softeer.ai/)

특징 : PC 화면 녹화 / PC 웹캠 녹화 / 모바일 녹화 / 복붙 불가 / 외부 IDE 사용불가 / 검색 불가 / java docs는 참고 가능

구성 : 3문제 (Java 3문제) 

방식 : 주어진 시간내에 모두 풀고, 가장 마지막에 제출한 답으로 제출되며, 시간 내에 계속 넘어올 수 있음

난이도 : 중상? 

설명 : softeer로 갈아타면서, 어려워졌다는 후기가 많은데, 역시 듣던거보다 어려워짐. 특정 알고리즘을 사용한것 보다도, 구현에 가까운 문제이고, softeer기준으로 레벨 2,3,4 1문제정도씩이 아닐까...싶음

특히나 softeer에 적응하지 못해서 환경에 적응하는데 30분정도 걸려서 시간이 많이 부족하고, 소스를 리팩토링하는것도 복붙이 안 되서 너무 까다롭고, 제약 사항이 많아서 힘든 기억.

부디 여러분은 여러번 풀고 적응한 상태에서 시험을 보시기를..!

팀바팀이지만, 커트라인으로 삼지 않고, 면접과 합산해서 보는 경우도 있다고해요

반응형
반응형

이슈

Python에서 loop(for)문으로 돌면서 특정 요소를 삭제시, 모든 요소를 체크하지 못하는 이슈

원인

Loop를 돌다가 삭제가 되면 다음 인덱스가 건너 띄워진다
(Ex. 위의 예제) [a,b,c,d]에서 Index=0인 a를 지우고, 다음 index인 1로 진행하면, [b,c,d]의 [1]인 c를 조회 => b를 skip!

 

해결

For문을 돌때  for l1 in list1[:]: 처럼 뒤에 [:]를 붙이면 복사면으로 루프를 돌리기 때문에 원하는 결과가 출력

(ex. for l1 in list1[:] :)

 


    list1 = ['a','b','c','d']
    list2 = ['a','b','e','f']
    for l1 in list1[:]:
        logging.info('비교대상 : %s', l1)
        if(l1 in list2):
            list1.remove(l1)
            list2.remove(l1)
    logging.info('비교 끝!  ')
    logging.info(list1)
    logging.info(list2)​

비교대상 : a

비교대상 : c

비교대상 : d

비교 ! 

['b', 'c', 'd']

['b', 'e', 'f']

 


   list1 = ['a','b','c','d']
    list2 = ['a','b','e','f']
    for l1 in list1:
        logging.info('비교대상 : %s', l1)
        if(l1 in list2):
            list1.remove(l1)
            list2.remove(l1)
    logging.info('비교 끝!  ')
    logging.info(list1)
    logging.info(list2)

비교대상 : a

비교대상 : b

비교대상 : c

비교대상 : d

비교 ! 

['c', 'd']

['e', 'f']

 

반응형
반응형

지난달 SK그룹/계열사에서 개발/운영 업무를 뽑는 공고가 있어서 지원했고,

여기는 서류전형+코딩테스트를 본 후에 종합적으로 판단해서 면접 여부를 확인하는 방식입니다.

채용 절차는 서류전형/코딩테스트 -1차면접 - 2차면접 순으로 진행되었으며, 1주일 이내에 결과가 나왔으며, 결과는 불합격입니다ㅠ

 

서류 전형

다른 대기업들과 비슷한 채용 사이트(career)를 사용하며, 구성도 거의 비슷해서 특별한 건 없었습니다.

기본정보 / 학력,자격증 / 경력 / 경력기술서 등등 작성하며, 퇴직 사유가 그나마 생각하기에 오래 걸리는 문항이었습니다

다른 SK 계열사와 중복해서 넣을 수 있지만, 한 계열사에서는 1군데만 지원 가능해요.

(여긴지, 다른 계열사인지 헷갈리는데) 자소서 항목은 따로 없었던것 같아요. 경력기술서 위주

반응형

코딩테스트

코딩테스트는 정해진 시간에 접속해서 풀었던것 같아요

사이트 : Codility

특징 : 모든 지문이 영어

구성 : 3문제 (SQL 1문제 / Java 2문제) 

방식 : 1문제당 제한시간내에 풀어서 제출하며, 한번 넘어가면 돌아올 수 없음

난이도 : 쉬운 편 (프로그래머스 기준 : 1정도)

특징 : 시간과의 싸움 / 특정 알고리즘을 사용하는 난이도 아님

 

 

후기 

3문제 모두 풀었지만, 종합적으로 판단하기 때문에 서류에서 탈락했을 가능성도 있지만, 어쨋든 탈락이지만

코테 난이도만 보면 어렵다고 할 순 없을것 같아요

 

 

반응형
반응형

문제 설명

Leo는 카펫을 사러 갔다가 아래 그림과 같이 중앙에는 노란색으로 칠해져 있고 테두리 1줄은 갈색으로 칠해져 있는 격자 모양 카펫을 봤습니다.

Leo가 본 카펫에서 갈색 격자의 수 brown, 노란색 격자의 수 yellow가 매개변수로 주어질 때 카펫의 가로, 세로 크기를 순서대로 배열에 담아 return 하도록 solution 함수를 작성해주세요.

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

나의 풀이 (java)

class Solution {
    public int[] solution(int brown, int yellow) {
//        수학적 풀이 필요 (1.for문 사용 2.근의공식) => 1로 풀었지만, 2가 성능이 좋음
//        yellow*brown = 가로*세로
//        yellow = (가로-2)*(세로-2)
        int[] answer = new int[2];
        for (int tempWidth = yellow+2; tempWidth > 0; tempWidth--) {
            int tempHeight = (brown+yellow)/tempWidth;
            if((tempWidth-2) * (tempHeight-2) == yellow){
                answer[0]=tempWidth;
                answer[1]=tempHeight;
                break;
            }
        }
        return answer;
    }
}

풀이 방법

  • 수학적 풀이 필요 (1.for문 사용 2.근의공식) => 1로 풀었지만, 2가 성능이 좋음
    • yellow*brown = 가로*세로
    • yellow = (가로-2)*(세로-2)

다른사람의 풀이 (java)

Good Idea : 근의 공식을 구현해 계산 -> 그렇다면, for문을 돌리지않고, 계산식만 한번 구하면 되기 때문에 성능이 아주 좋음 (단 가독성은 좀 떨어질수도..)

느낀점

코테에서는 종종 수학적 접근법이 중요한 경우가 있다.

그렇지 않으면, 모든 경우를 뒤져보면 된다

반응형
반응형

문제 설명

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호 가로 길이 세로 길이
1 60 50
2 30 70
3 60 30
4 80 40
가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.

모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

나의 풀이 (java)

class Solution {
    public int solution(int[][] sizes) {
        int max = 0;
        int min = 0;
        for (int[] size : sizes) {
            int paramMax = Math.max(size[0], size[1]);
            int paramMin = Math.min(size[0], size[1]);

            if (paramMax > max) {
                max = paramMax;
            }

            if (paramMin > min) {
                min = paramMin;
            }
        }
        return max * min;
    }
}

풀이 방법

  • 모든 지갑마다 가로>세로 되도록 "sizes"를 정렬
  • 게중에 가장 큰 가로/세로 길이를 구함

 

느낀점

모든 경우의 수를 확인해야하는 완전 탐색의 풀이법은

역시 반복문과 조건문으로 빠짐없이 모두 체크하는것!

반응형
반응형

문제 설명

하드디스크는 한 번에 하나의 작업만 수행할 수 있습니다. 디스크 컨트롤러를 구현하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법은 요청이 들어온 순서대로 처리하는 것입니다.
각 작업에 대해 [작업이 요청되는 시점, 작업의 소요시간]을 담은 2차원 배열 jobs가 매개변수로 주어질 때, 작업의 요청부터 종료까지 걸린 시간의 평균을 가장 줄이는 방법으로 처리하면 평균이 얼마가 되는지 return 하도록 solution 함수를 작성해주세요. (단, 소수점 이하의 수는 버립니다)

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

나의 풀이 (java) = 다른 사람의 풀이

import java.util.Arrays;
import java.util.PriorityQueue;

class Solution {
    public int solution(int[][] jobs) {
        // 총 시간은 대기시간(가변)+실행시간(불변)이므로, 대기시간이 짧을수록 짧아진다
        // 대기시간(=시작시간-요청시간)을 짧게 하려면, 수행시간이 짧은걸 먼저 처리(SJF)

        // 중요 개념 : 선점SJF 와 비슷
        // 작업을 요청 시점 순으로 담고 있는 작업 큐
        // 소요시간이 적은 순으로 작업을 수행하는 작업 큐
        // 요청 시점에 가능한 작업들을 작업 큐에 넘겨주면, 소요시간이 적은 순서대로 우선순위를 부여하여 작업을 수행

        int seconds = 0;
        // jobs를 요청시간으로 정렬(asc)하는 prioirtyQueue 생성
        PriorityQueue<Integer[]> jobQue = new PriorityQueue<>((o1, o2) -> o1[0].compareTo(o2[0]) );

        // int[] -> Integer[] -> prioirtyQueue에 삽입
        for (int[] job : jobs) {
            jobQue.add(Arrays.stream(job).boxed().toArray(Integer[]::new));
        }

        // 계산
        int size = jobQue.size();
        int totalSeconds = 0;
        while(!jobQue.isEmpty()){
            if(seconds < jobQue.peek()[0]){
                seconds++;
                continue;
            }

            // 해당 시점에 실행할 수 있는 job관리 큐
            PriorityQueue<Integer[]> availableQue = new PriorityQueue<>((o1,o2) -> o1[1].compareTo(o2[1]));
            while(!jobQue.isEmpty() && jobQue.peek()[0] <= seconds){
                availableQue.add(jobQue.poll());
            }

            // 대기시간(=시작시간-요청시간) + 실행시간
            Integer[] currentJob = availableQue.poll();
            totalSeconds += seconds - currentJob[0] + currentJob[1];

            // 쓰지 않은 job은 모두 복구
            jobQue.addAll(availableQue);

            // 현재 작업 실행 완료 시점으로 jump!
            seconds += currentJob[1];
        }

        return Math.round(totalSeconds/size);
    }
}

풀이 방법

  • 선점 SJF와 비슷 = 작업을 요청 시점 순으로 담아서 처리
    • 잘못된 접근 : 작업시작 시간으로 정렬하는것에 집중한것이 실패의 요인
    • 올바른 접근 : 당시의 최적의 해를 구하는 탐욕법과 비슷
      => 매 시점마다 소요시간이 적게 걸리는 작업을 먼저 처리하는게 효율적이라는 풀이를 도출하는것이 중요하다
  • 풀이
    • 작업 요청 시간 별로 정렬-> 첫번째 실행 -> 완료 시점에서 실행가능한 작업중 완료시간이 가장 짧은 작업 실행 * n 번 실행

느낀점

  • 그리디(탐욕법) : 당시의 최적의해를 찾는 방식을 계속하는 방식 -> 이 내용과 비슷
  • 주요 로직
    작업 요청 시간 별로 정렬-> 첫번째 실행 -> 완료 시점에서 실행가능한 작업중 완료시간이 가장 짧은 작업 실행 * n 번 실행
반응형

+ Recent posts