<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jimmy_devkid.log</title>
        <link>https://velog.io/</link>
        <description>문을 끝없이 두드리는 사람</description>
        <lastBuildDate>Tue, 06 Feb 2024 07:21:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. jimmy_devkid.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jimmy_devkid" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[개발일지] 24.02.05 - TypeScript constructor 관련 러닝]]></title>
            <link>https://velog.io/@jimmy_devkid/%EA%B0%9C%EB%B0%9C%EC%9D%BC%EC%A7%80-24.02.05-TypeScript-constructor-%EA%B4%80%EB%A0%A8-%EB%9F%AC%EB%8B%9D</link>
            <guid>https://velog.io/@jimmy_devkid/%EA%B0%9C%EB%B0%9C%EC%9D%BC%EC%A7%80-24.02.05-TypeScript-constructor-%EA%B4%80%EB%A0%A8-%EB%9F%AC%EB%8B%9D</guid>
            <pubDate>Tue, 06 Feb 2024 07:21:30 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-상황">문제 상황</h2>
<hr>
<p>프론트에서 applier 들에 대한 세부정보를 불러오면 단순하게 applier 와 관련된 정보 뿐 아니라 applier의 계정정보가 모두 반환되는 사태가 발생하였다.</p>
<p>이를 해결 하기 위해 ShowApplierDto 클래스를 생성했다. 그러나 계속 password 정보가 나오는 것이었다.</p>
<h2 id="해결방법">해결방법</h2>
<hr>
<p>문제의 원인부터 말하자면 constructor의 인수를 private으로 선언했기 때문이었다.
<del>문제의 코드</del></p>
<pre><code class="language-ts">export class ShowApplierDto {
  businessId: string;
  companyName: string;
  ceoName: string;
  ...

  constructor(private applier: Applier) {
    this.businessId = applier.businessId;
    this.companyName = applier.companyName;
    this.ceoName = applier.ceoName;
    ...
  }
}
</code></pre>
<p>이렇게 private을 먹이면 Controller에서 반환되는 ShowApplierDto에서 Applier 객체가 나온 후 쿼리 결과가 나오게 된다.</p>
<pre><code class="language-json">ShowApplierDto {
  applier: Applier {
    id: 2,
    businessId: &#39;34-56-678901&#39;,
    password: &#39;$2a$10$ZfH9z9k0Hph7svbEsZPAMufZt97zj1ZZqJYJaPEXJKtH0GXc2npBa&#39;,
    companyName: &#39;AA건설&#39;,
    ceoName: &#39;김대표&#39;,
    companyAddress: &#39;경기도 파주시 00로 xxx, 3층&#39;,
    ...
  },
  businessId: &#39;34-56-678901&#39;,
  companyName: &#39;AA건설&#39;,
  ceoName: &#39;김대표&#39;,
  companyAddress: &#39;경기도 파주시 00로 xxx, 3층&#39;,
  ...
}</code></pre>
<p>처음에는 저렇게 password가 나온 이유가 nestJS 라이프 사이클 상에서 Guard에서 반환되는 것이라 생각했다.</p>
<p>그러나 JSON을 뜯어보니 applier 객체가 불러져왔기 때문이었다.</p>
<p>단순하게 private을 지우니 applier가 나오지 않았다.</p>
<h2 id="레슨런">레슨런</h2>
<hr>
<p>우선 왜이러는지에 대해 알아보니...</p>
<p>TypeScript는 클래스의 constructor에서 Access Modifier(private, public, protected)를 사용한 매개변수는 자동으로 필드로 들어가게 된다.</p>
<p>그래서 private을 넣으면 response에 applier가 들어가게 된다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[인프런 코테] 2번. 대소문자변환]]></title>
            <link>https://velog.io/@jimmy_devkid/%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%BD%94%ED%85%8C-2%EB%B2%88.-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@jimmy_devkid/%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%BD%94%ED%85%8C-2%EB%B2%88.-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90%EB%B3%80%ED%99%98</guid>
            <pubDate>Thu, 25 Jan 2024 04:57:12 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>설명</p>
<p>대문자와 소문자가 같이 존재하는 문자열을 입력받아 대문자는 소문자로 소문자는 대문자로 변환하여 출력하는 프로그램을 작성하세요.</p>
<p>입력
첫 줄에 문자열이 입력된다. 문자열의 길이는 100을 넘지 않습니다.</p>
<p>문자열은 영어 알파벳으로만 구성되어 있습니다.</p>
<p>출력
첫 줄에 대문자는 소문자로, 소문자는 대문자로 변환된 문자열을 출력합니다.</p>
<p>예시 입력 1 </p>
<p>StuDY
예시 출력 1</p>
<p>sTUdy</p>
<h2 id="해결방법">해결방법</h2>
<p>Character 클래스의 isUpperCase() 와 isLowerCase() 메소드를 적절히 활용하여 해결하였다.</p>
<p>강의에서는 ASCII 코드로 문제를 해결하였다.</p>
<h2 id="배운점">배운점</h2>
<p>어떻게 보면 상식 선에서 대문자 알파벳과 소문자 알파벳의 아스키코드를 알고있는 것이 좋다.</p>
<blockquote>
<p>대문자 알파벳: 65 ~ 90
소문자 알파벳: 97 ~ 122</p>
</blockquote>
<p>따라서 메소드를 따로 쓰지 않고 소문자에서 대문자로 바꾸고 싶다면 char에 바로 32를 빼면된다.</p>
<p>반대로 대문자에서 소문자로 바꾸고 싶다면 char에서 32를 더하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[인프런 코테]  1번.  문자찾기]]></title>
            <link>https://velog.io/@jimmy_devkid/%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%BD%94%ED%85%8C-1%EB%B2%88.-%EB%AC%B8%EC%9E%90%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@jimmy_devkid/%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%BD%94%ED%85%8C-1%EB%B2%88.-%EB%AC%B8%EC%9E%90%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Thu, 25 Jan 2024 04:51:47 GMT</pubDate>
            <description><![CDATA[<p>코딩테스트를 다시 슬슬 준비하려고 이번에 인프런 강의를 끊었다. 하루에 최소 한 문제씩 풀고 그에 대한 인사이트를 얻어보려고 한다.</p>
<hr>
<h2 id="문제">문제</h2>
<p>설명</p>
<p>대문자와 소문자가 같이 존재하는 문자열을 입력받아 대문자는 소문자로 소문자는 대문자로 변환하여 출력하는 프로그램을 작성하세요.</p>
<p>입력
첫 줄에 문자열이 입력된다. 문자열의 길이는 100을 넘지 않습니다.</p>
<p>문자열은 영어 알파벳으로만 구성되어 있습니다.</p>
<p>출력
첫 줄에 대문자는 소문자로, 소문자는 대문자로 변환된 문자열을 출력합니다.</p>
<h2 id="해결방법">해결방법</h2>
<p>문자열을 입력받아서 for문으로 char를 하나씩 조회하여 일치한다면 answer에 개수를 추가하는 방식으로 해결하였다.</p>
<h2 id="배운점">배운점</h2>
<p>발전된 for 구문을 활용하여 문제를 해결했다.</p>
<pre><code class="language-java">    for(char x : str.toCharArray()){
        if(x==t) answer++;
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[flutter#3]]></title>
            <link>https://velog.io/@jimmy_devkid/flutter3</link>
            <guid>https://velog.io/@jimmy_devkid/flutter3</guid>
            <pubDate>Sat, 18 Feb 2023 05:37:34 GMT</pubDate>
            <description><![CDATA[<h1 id="3에서-만들-것">#3에서 만들 것</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/jimmy_devkid/post/f2fc7992-3612-4ec9-96a1-7050719953a6/image.png" alt="">
버튼 등의 기능은 없지만 디자인을 그대로 만들어볼 것이다.</p>
<h1 id="30-header-만들기">#3.0 Header 만들기</h1>
<hr>
<p>다음 부분을 만들어볼 것이다.
<img src="https://velog.velcdn.com/images/jimmy_devkid/post/5e5e4978-2659-47a6-a6f9-754580854211/image.png" alt=""></p>
<p>위를 구현한 코드는 다음과 같다.</p>
<pre><code class="language-dart">class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Color(0xFF181818),
        body: Padding(
          padding: EdgeInsets.symmetric(
            horizontal: 40,
          ),
          child: Column(
            children: [
              SizedBox(
                height: 80,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Text(
                        &#39;Hey, Selena&#39;,
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 28,
                          fontWeight: FontWeight.w800,
                        ),
                      ),
                      Text(
                        &#39;Welcome back&#39;,
                        style: TextStyle(
                          fontSize: 18,
                          color: Colors.white.withOpacity(0.8),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}</code></pre>
<ol>
<li><p>Column과 Row
웹 프론트엔드와 마찬가지로 박스로 생각하면 쉽다. 전체적인 화면구성은 세로로 쌓여있는 구조로, Column 구조이다. 그리고 그 안의 헤더 부분을 보면 가로로 이어져 있는 Row 구조를 띄고 있다. 이 구조를 잘 이해해야 한다. 이들은 각각 하나의 child를 가지고 이들은 list 자료형이다. 마우스를 갖다 대면 알 수 있다. Column에서 가운데 정렬 혹은 왼쪽 정렬, 오른쪽 정렬을 하기 위해서는 CrossAxisAlignment를 사용한다. Row에서는 반대이다. flexbox와 유사하다. 정리하면 Row의 가로가 main, Column의 세로가 main이다. </p>
</li>
<li><p>SizedBox
Column에서 하나의 속성이 위에 딱 붙을 때 조금은 떨어뜨려놓을 수 있도록 빈 박스를 만드는 것이다. height 등을 지정할 수 있다.</p>
</li>
<li><p>Text 및 Text 관련 속성들
CSS와 상당히 유사한데 조심할 점은 지정할 때 자료형을 잘 봐야한다. 하나 알아둬야 하는 것은 withOpacity이다. 이는 투명도를 조절할 수 있다.</p>
</li>
<li><p>Padding
Padding은 html과 css 처럼 사용할 수 있는데 어떤 방식으로 패딩을 하는지에 따라 사용할 속성이 달라진다. 여기서는 Edgeinsets를 사용했다. </p>
</li>
</ol>
<p>5.Color
색을 지정하기 위해서 Colors를 이용할 수 있지만 컬러코드를 따온다면 다음과 같이 0xFF를 쓰고 6자리 코드를 적음으로써 지정할 수 있다.</p>
<pre><code class="language-dart">backgroundColor: Color(0xFF181818),</code></pre>
<h1 id="31-devtool-사용">#3.1 devtool 사용</h1>
<hr>
<p>devtool은 vscode 상에서 다음의 버튼을 클릭함으로써 활성화할 수 있다.
<img src="https://velog.velcdn.com/images/jimmy_devkid/post/248dcf9e-053b-4744-a19c-053b6e0c4572/image.png" alt="">
이 툴을 사용하면 우리가 크롬에서 사용했던 개발자 도구와 유사한 기능들, 혹은 더 나은 기능들을 사용할 수 있다.</p>
<h1 id="32-container-위젯">#3.2 container 위젯</h1>
<hr>
<p>이번 강의에서는 다음 부분을 만들었다.
<img src="https://velog.velcdn.com/images/jimmy_devkid/post/806182e8-a469-4166-a0af-03f28d1615c6/image.png" alt=""></p>
<p>Total Balance와 금액 텍스트는 다음의 코드를 입력하여 완성하였다. 이에 대한 내용은 위와 동일하니 패스한다.</p>
<pre><code class="language-dart">SizedBox(
                height: 120,
              ),
              Text(
                &#39;Total Balance&#39;,
                style: TextStyle(
                  fontSize: 22,
                  color: Colors.white.withOpacity(0.8),
                ),
              ),
              SizedBox(
                height: 5,
              ),
              Text(
                &#39;\$5 194 482&#39;,
                style: TextStyle(
                  fontSize: 44,
                  fontWeight: FontWeight.w600,
                  color: Colors.white,
                ),
              ),</code></pre>
<p> 한가지 알아두어야할 것은 $를 그대로 쓰면 그 뒤에 오는 5를 변수 취급하기 때문에 역슬래시를 이용하여 string임을 명시해줘야한다.</p>
<p> 다음은 버튼을 만드는 것인데 이는 Container라는 위젯을 사용한다. html의 div와 유사하다. 우선은 노란 버튼 하나만 만들었다. 코드는 아래와 갇다.</p>
<pre><code class="language-dart"> Row(
                children: [
                  Container(
                      decoration: BoxDecoration(
                        color: Colors.amber,
                        borderRadius: BorderRadius.circular(45),
                      ),
                      child: Padding(
                        padding:
                            EdgeInsets.symmetric(vertical: 20, horizontal: 50),
                        child: Text(
                          &#39;Transfer&#39;,
                          style: TextStyle(
                            fontSize: 20,
                          ),
                        ),
                      )),
                ],
              ),</code></pre>
<p>우선 버튼 2개가 가로로 배치되어있으므로 Row 위젯을 사용한다. 그리고 첫번째 container를 작성한다. container를 꾸밀 때는 decoration을 이용한다. BoxDecoration을 이용하여 그 안에서 색깔 혹은 보더를 지정할 수 있다. </p>
<p>버튼 안의 텍스트를 패딩 없이 하면 글자크기에 딱 맞는 정도의 박스가 생성되는데 우리가 만들 버튼은 어느 정도 패딩이 존재하기 때문에 패딩을 지정해줬다.</p>
<h1 id="33-vscode-파란줄-없애기--유용한-설정-활성화">#3.3 vscode 파란줄 없애기 + 유용한 설정 활성화</h1>
<hr>
<p>vscode로 dart를 사용하다보면 파란 물결 줄이 계속 뜬다. 이는 경고 메세지 때문이다. const를 권고하는 내용이다. 그래서 실제로 Color같은 속성 앞에 const를 쓰면 줄이 사라진다. 이것을 하나하나 하면서 물결 줄을 없애기에는 너무 귀찮고 정확하지 않을 수 있다. 그래서 vscode의 설정을 통해 이를 해결한다. 명령 팔레트에 open users setting을 치면 json 파일이 열린다. 거기에 다음을 추가한다.</p>
<pre><code class="language-json">&quot;editor.codeActionsOnSave&quot;: {&quot;source.fixAll&quot;: true},</code></pre>
<p>이러면 줄이 다 사라진다.</p>
<p>또 하나의 유용한 기능은 부모-자식 간의 관계를 시각적으로 나타내주는 기능이다. 다음 코드를 위의 설정 json 파일에 넣어준다.</p>
<pre><code class="language-json">&quot;dart.previewFlutterUiGuides&quot;: true,</code></pre>
<p>이렇게 되면 아래와 같이 종속관계가 시각적으로 나타난다.
<img src="https://velog.velcdn.com/images/jimmy_devkid/post/aca5c35c-5d68-4b10-9cab-88febee2ad7a/image.png" alt=""></p>
<h1 id="34-code-action---wrapping에-유용한-도구">#3.4 code action - wrapping에 유용한 도구</h1>
<hr>
<p>헤더를 만들 때 패딩을 줘야 했었다. 그래서 방대한 양을 잘라내기 해서 padding의 괄호 안에 붙여넣기를 했다. 더 방대한 양도 동일하게 하기에는 어려움이 있고 이 자체가 귀찮은 일이다. 그래서 우리는 code action을 사용한다. 이는 간혹가다 보이는 노란 전구이다. 이걸 누르면 우리가 적용하고 싶은 위젯으로 둘러싸게 해준다. 혹은 단축키 &#39;커맨드 + .&#39;를 둘러싸고자 하는 최상위 위젯에 커서를 두고 누르면 동일한 기능을 사용할 수 있다.</p>
<h1 id="35-widget-재사용">#3.5 widget 재사용</h1>
<hr>
<p>시작하기에 앞서 vscode에 error lens 확장팩을 다운로드한다. 위에서 만든 버튼 옆에 버튼 하나를 더 만드려고 한다. 단순하게 복사붙여넣기 하고 배경, 텍스트 등을 바꾸기만 하면 완성이다. 다만 이렇게 하다보면 다음과 같은 경고창이 나타난다.
<img src="https://velog.velcdn.com/images/jimmy_devkid/post/fc2f08e7-1d94-407b-bd09-8e7a34febf26/image.png" alt="">
이것은 픽셀이 패딩에 오버플로우 됐음을 알려준다. 따라서 적절하게 전체 패딩을 줄여준다.</p>
<p>그리고 위에 보면 현재 버튼 끼리 딱 붙어있으므로 다음의 속성을 Row에 추가하여 떨어뜨려준다.</p>
<pre><code class="language-dart">mainAxisAlignment: MainAxisAlignment.end,</code></pre>
<p>그러나 이렇게 복사 붙여넣기 하는 것은 너무나 비효율적이다. 그러므로 우리는 재사용할 수 있게 만들어야한다. 단순하게 Container 앞에서 전구를 눌러 &#39;extract widget&#39;을 할 수 있지만, 공부를 위해 기초적인 방법으로 진행했다.</p>
<p>먼저 main.dart 파일과 동일한 폴더 내에 widgets 폴더를 형성하고 그 안에 Button.dart 파일을 형성한다. 그 안에 새로운 위젯을 설정하고 return 부분에 처음에 디자인했던 Container를 복사붙여넣기 한다. 그럼 다음과 같은 코드를 작성하게 된다.</p>
<pre><code class="language-dart">import &#39;package:flutter/material.dart&#39;;

class Button extends StatelessWidget {
  final String text;
  final Color bgColor;
  final Color textColor;

  const Button(
      {super.key,
      required this.text,
      required this.bgColor,
      required this.textColor});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: bgColor,
        borderRadius: BorderRadius.circular(45),
      ),
      child: Padding(
        padding: const EdgeInsets.symmetric(
          vertical: 20,
          horizontal: 50,
        ),
        child: Text(
          text,
          style: TextStyle(
            fontSize: 20,
            color: textColor,
          ),
        ),
      ),
    );
  }
}</code></pre>
<p>우리는 Button 위젯을 재사용하면서 텍스트, 배경색깔, 텍스트 색깔을 바꿔야한다. 그러므로 프로퍼티들을 지정해주고 그 다음 생성자를 만들어준다. 이때 Button은 const가 아니므로 const 지워준다. 이렇게 만든 Button 위젯을 다음과 같이 사용할 수 있다.</p>
<pre><code class="language-dart">const Button(
             text: &#39;Transfer&#39;,
             bgColor:  Color(0xFFF1B33B),
             textColor: Colors.black,
             ),
const Button(
             text: &#39;Request&#39;,
             bgColor:  Color(0xFF1F2123),
             textColor: Colors.white,
             ),</code></pre>
<h1 id="37-아이콘-overflow">#3.7 아이콘 overflow</h1>
<hr>
<h3 id="iconicons">Icon(Icons.~)</h3>
<p>다트에는 다트 자체적으로 제공하는 아이콘이 있다. 그것을 사용하기 위해선 Icon()을 쓰면 된다. 예시는 아래와 같다.</p>
<pre><code class="language-dart">Icon(
Icons.euro_rounded,
size: 88,
color: Colors.white,
),</code></pre>
<h3 id="transfomscale">transfom.scale</h3>
<p>container 안에 내용물의 사이즈를 변화시키면 그 사이즈에 따라 container의 크기도 같이 변한다. 만약 내용물의 사이즈만 변화시키고 싶을 때 transformation.scale을 사용한다. 그 예시는 아래와 같다.</p>
<pre><code class="language-dart">Transform.scale(
scale: 2.2,
...),</code></pre>
<h3 id="transformtranslateoffset">transform.translate(Offset:~)</h3>
<p>어떤 객체의 위치를 절대적으로 움직이기 위해 사용할 수 있다. 지금까지는 spaceBetween 으로 간격 띄우기만을 했다면 이제는 직접적으로 OffSet을 주어서 위치를 지정할 수 있다. </p>
<pre><code class="language-dart">Transform.translate(
offset: const Offset(-5, 12),
...)</code></pre>
<h3 id="container의-clipbehavior">Container의 clipBehavior</h3>
<p>크기가 컨테이너를 넘는 아이콘이 있을 때 넘은 것을 가릴 수 있게 하는 것이다. 다른 옵션도 있으니 확인하면 된다. 다음과 같이 사용한다.</p>
<pre><code class="language-dart">...
clipBehavior: Clip.hardEdge,
...</code></pre>
<p>Clip.None이면 컨테이너를 넘어도 자르지 않고, Clip.hardEdge이면 컨테이너를 넘은 부분을 잘라낸다.</p>
<h1 id="38-reusable-card">#3.8 reusable card</h1>
<hr>
<h3 id="만든-클래스에-새로운-프로퍼티-삽입">만든 클래스에 새로운 프로퍼티 삽입</h3>
<p><img src="https://velog.velcdn.com/images/jimmy_devkid/post/908e0334-faf7-49c8-badc-f9581dc591bb/image.png" alt="">
카드를 재사용하기 위해서 버튼을 재사용하기 위해 위젯 파일을 따로 만든 것과 동일한 작업을 한다.<br>그러나 결과물을 보면 모든게 다 동일한데 비트코인 카드만 배경색과 글자색이 반전된 것을 확인할 수 있다. 이를 위해 추가적인 프로퍼티를 넣어야한다. IsInverted라는 변수를 지정하여 구현하였고 코드는 아래와 같다.</p>
<pre><code class="language-dart">class CurrencyCards extends StatelessWidget {
  ...
  final bool IsInverted;
  ...
  const CurrencyCards({
    super.key,
    required this.name,
    required this.code,
    required this.amount,
    required this.icon,
    required this.IsInverted,
  });
  @override
  Widget build(BuildContext context) {
    return Container(
      clipBehavior: Clip.hardEdge,
      decoration: BoxDecoration(
        color: IsInverted ? Colors.white : _blackColor,
        borderRadius: BorderRadius.circular(20),
      ),
      ...
      };</code></pre>
<p>IsInverted도 입력값이 필요하므로 생성자를 만들어줘야한다. 그렇기 때문에 required this.IsInverted 를 넣어야한다. 이렇게 만든 변수는<br>color: IsInverted ? Colors.white : _blackColor  </p>
<p>처럼 물음표 조건문을 통해 조건에 따라 속성이 변하도록 설정할 수 있다.</p>
<h3 id="singlechildscrollview">SingleChildScrollView</h3>
<p>이것은 사용자가 화면을 스크롤 할 수 있도록 해주는 위젯이다. </p>
<pre><code class="language-dart">home: Scaffold(
        backgroundColor: const Color(0xFF181818),
        body: SingleChildScrollView(
...</code></pre>
<p>이처럼 Scaffold의 body에 위젯으로 씌워 구현한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[코드플러스-약수]]></title>
            <link>https://velog.io/@jimmy_devkid/%EC%BD%94%EB%93%9C%ED%94%8C%EB%9F%AC%EC%8A%A4-%EC%95%BD%EC%88%98</link>
            <guid>https://velog.io/@jimmy_devkid/%EC%BD%94%EB%93%9C%ED%94%8C%EB%9F%AC%EC%8A%A4-%EC%95%BD%EC%88%98</guid>
            <pubDate>Mon, 30 Jan 2023 06:10:38 GMT</pubDate>
            <description><![CDATA[<h1 id="1037번-약수">1037번-약수</h1>
<hr>
<p>1과 자기 자신을 제외한 약수들이 주어질 때 그 수를 구하는 문제이다. 결론적으로, 약수 중 가장 작은 값과 큰 값을 구해 곱하면 된다. 나의 풀이는 아래와 같다.</p>
<pre><code class="language-python">n = int(input())
div=list(map(int, input().split()))
ans = 0

if n == 1:
    ans = div[0]*div[0]
else:
    ans = max(div)*min(div)
print(ans)</code></pre>
<p>처음에는 입력 시에 정렬된 상태임을 가정하고 풀었는데 그것이 아니었다. 그래서 시간을 좀 잡아먹었다.</p>
<p>이 문제에서 주목할 만한 것은 띄어쓰기로 되어있는 문자열을 받아서 그것을 하나하나 잘라 리스트로 다룰 때이다. 그것을 위한 코드는 다음과 같다.</p>
<pre><code class="language-python">div=list(map(int, input().split()))</code></pre>
<h1 id="17427번-약수의-합2">17427번-약수의 합2</h1>
<hr>
<p>이 문제는 시키는 대로 코드를 작성했다. 그래서 아래와 같은 코드를 작성했다.</p>
<pre><code class="language-python">n = int(input)

def function_f(n):
    i = 1
    ans = 0
    while i &lt;= n:
        if n%i == 0:
            ans += i
        i += 1
    return ans

ans = 0
for i in range(n):
    ans += function_f(i+1)
print(ans)</code></pre>
<p>그러나 계속 런타임에러가 떴다. 제한 시간을 살피지 않은 것이다. 제한 시간은 0.5초 이다. 그러나 위의 코드대로 복잡도를 계산해보면 아무리 줄여봐야 O(루트 N)이다. 즉, N의 최대값인 1000000을 집어넣어보면 복잡도가 약 10초 정도이다. 따라서 약수를 직접구하는 방법으로는 제한 시간을 맞출 수 없다.</p>
<p>따라서 배수로 찾아가야한다. 어찌됐건 N이하의 숫자들의 모든 약수를 구하는 것이기 때문에 N을 N보다 작은 자연수로 나눈 개수 만큼의 약수가 들어있을 것이다. 다음 이미지로 이해할 수 있다.
<img src="https://velog.velcdn.com/images/jimmy_devkid/post/3ea13744-c454-40d2-a242-59388d871e83/image.png" alt="">
이를 토대로 배수의 개수를 구하고 그 수를 곱한 것을 합하여 구하는 방법은 단순하게 연산만 하는 것이므로 O(N)의 복잡도를 가진다. 따라서 제한 시간을 만족한다. 아래의 코드로 구현했다.</p>
<pre><code class="language-python">n = int(input())
ans = 0
i = 1
while i &lt;= n:
    ans += (n//i*i)
    i += 1
print(ans)</code></pre>
<h1 id="17425번-약수의-합">17425번-약수의 합</h1>
<hr>
<p>위의 약수의 합 2 문제의 알고리즘을 사용하면 최대시간이 약 1000초이다. 그렇기 때문에 우리는 배수의 방법을 적용할 것이다. 한 가지 알고 있는 사실은 N까지의 수 중 약수인 수의 개수가 아닌 수보다 월등히 적다. 그러므로 우리는 N의 최댓값까지 약수의 합을 전부 구하고 입력된 수를 그 안에서 찾아서 출력할 것이다. 이 경우 복잡도는 O(NlogN)이다. 아래는 이를 구현한 코드이다.</p>
<pre><code class="language-python">MAX = 1000000
div = [1] * (MAX+1)
s = [0] * (MAX+1)

for i in range(2, MAX+1):
    j = 1
    while i*j &lt;= MAX:
        div[i*j] += i
        j += 1
for i in range(1, MAX+1):
    s[i] = s[i-1] + div[i]

n = int(input())
ans = []
for _ in range(n):
    i = int(input())
    ans.append(s[i])

print(&#39;\n&#39;.join(map(str, ans))+&#39;\n&#39;)</code></pre>
<p>div는 N 까지의 수의 각 수에 대한 f함수 값, 즉 약수의 합을 나타낸 것이다. g함수 값은 s 리스트에 담겨있다. 리스트의 길이를 MAX+1로 한 이유는 인덱스 0의 값을 신경쓰지 않게 하기 위함 인 것 같다. </p>
<p>여기서 알게 된 것이 2가지가 있다.
하나는 unscored _ 이다. 이는 위 처럼 인덱스가 필요없이 단순 반복을 위한 도움장치이다.</p>
<p>두번째는 리스트의 세로 출력 방법이다. 전에는 반복문으로 주르륵 출력했다면 이 코드에서는 직접 그 형태의 반복문을 \n을 이용하여 만들었다.</p>
<pre><code class="language-python">print(&#39;\n&#39;.join(map(str, ans))+&#39;\n&#39;)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[dart#3(nomad)]]></title>
            <link>https://velog.io/@jimmy_devkid/dart3nomad</link>
            <guid>https://velog.io/@jimmy_devkid/dart3nomad</guid>
            <pubDate>Sun, 08 Jan 2023 15:31:09 GMT</pubDate>
            <description><![CDATA[<h1 id="defining-function">Defining Function</h1>
<hr>
<pre><code class="language-dart">void sayHello(String name){
  print(&quot;Hello $name! Nice to meet you!&quot;); 
}</code></pre>
<p>void는 C언어에서와 같이 리턴이 없는 함수를 정의할 때 쓴다.</p>
<pre><code class="language-dart">String sayHello(String potato){
  return &quot;Hello $potato! Nice to meet you!&quot;;
}</code></pre>
<p>위 처럼 리턴 값이 String인 경우 void 대신 String을 쓴다. String을 리턴하는 함수라는 뜻인 것이다.</p>
<p>이 함수를 main 함수 내에서 사용하는 예시는 아래와 같다.</p>
<pre><code class="language-dart">String sayHello(String potato){
  return &quot;Hello $potato! Nice to meet you!&quot;;
}

void main() {
  print(sayHello(&#39;jiho&#39;));
}</code></pre>
<br>

<p>fat arrow(화살표 함수)를 이용해서 함수의 리턴을 지정할 수 있다.</p>
<pre><code class="language-dart">String sayHello(String potato) =&gt; &quot;Hello $potato! Nice to meet you!&quot;;</code></pre>
<p>화살표를 지정하는 것이 리턴할 것이다. 이 함수는 한줄짜리 코드 함수일 때 사용하면 공간절약을 할 수 있다.</p>
<h1 id="named-argument">named argument</h1>
<hr>
<p>여러개의 인수를 받는 함수를 사용할 때 그 안의 인수를 순서에 맞게 알맞은 자료형으로 넣어야 에러가 발생하지 않는다. 그러나 인수가 정말 많을 경우 사용자가 이를 헷갈려 할 수 있다. 따라서 딕셔너리 형태로 쓰되, 순서에 구애받지 않게 하는 것을 named argument 기능이라고 한다. 예시는 아래와 같다.</p>
<pre><code class="language-dart">String sayHello({
  String name = &#39;anon&#39;,
  int age = 99,
  String country = &#39;wakanda&#39;,
}){
  return &quot;Hello $name, you are $age, and you come from $country.&quot;;
}

void main() {
  print(sayHello(
    name:&#39;jiho&#39;,
    country : &#39;korea&#39;,
    age : 25,
  ));
}</code></pre>
<p>함수의 인풋에 {}을 씌워 set처럼 만든 후 각각에 대한 디폴트 값을 지정해주면 순서와 상관 없이 사용할 수 있다. 디폴트 값을 사용하는 이유는 다트 언어는 null safety 중요시 하기 때문이다.
null safety를 방지하기 위해 &#39;required&#39;를 선언할 수도 있다.</p>
<pre><code class="language-dart">required String name,
required int age,
required String country,</code></pre>
<p>required modifier는 메인 함수에서 사용될 때 인풋이 반드시 입력되어야 함을 나타낸다.</p>
<h1 id="optional-position-parameter">optional position parameter</h1>
<hr>
<p>position parameter는 순서를 기억하고 있어야하는 함수 인풋이다.이 상태의 인풋 인수들은 모두 required이다. 그러나 선택적으로 하나의 인수에 대해서는 required를 적용시키지 않고자 할 때 조건문을 사용하여 구현할 수 있다.</p>
<pre><code class="language-dart">String sayHello(
  String name,
  int age,
  [String? country = &#39;cuba&#39;]) =&gt; &#39;Hello $name, you are $age years old from $country&#39;;


void main() {
  var results = sayHello(&#39;jiho&#39;, 12);
  print(results);
}</code></pre>
<p>중괄호 []를 침으로서 그 안에 만약 인수가 입력되지 않는다면 디폴트 값을 나타내게 할 수 있다.</p>
<h1 id="qq-연산자">QQ 연산자</h1>
<hr>
<p>??와 ?= 연산에 대해 알아볼 것이다. </p>
<pre><code class="language-dart">String capitalizeName(String? name){
  if(name != null){
    return name.toUpperCase();
  }
  return &#39;ANON&#39;;
}</code></pre>
<p>String?을 씀으로써 이 변수가 null이어도 되고 null이 아니어도 되는 것이다.
위 함수를 fat arrow 형식으로 나타내면 다음과 같다.</p>
<pre><code class="language-dart">String capitalizeName(String? name)=&gt; name != null ? name.toUpperCase() : &#39;ANON&#39;;</code></pre>
<p>이 함수 코드를 QQ operator(??)를 이용하면 다음과 같이 간단하게 만들 수 있다.</p>
<pre><code class="language-dart">String capitalizeName(String? name)=&gt; name?.toUpperCase() ?? &#39;ANON&#39;;</code></pre>
<p>왼쪽이 null이면 ?? 오른쪽의 것을 리턴하고 왼쪽이 null이 아니면 그대로 왼쪽 값을 리턴한다.
<br>
??= 연산자는 null일수도 있는 변수가 null이라면 해당 값으로 초기화하는 연산을 한다. 예시는 다음과 같다.</p>
<pre><code class="language-dart">void main() {
  String? name;
  name ??= &#39;jiho&#39;;
  name ??= &#39;ANON&#39;;
  print(name);
}</code></pre>
<p>위 코드에서 name은 null 이기 때문에 jiho가 저장되고 그 이후에는 null이 아니기 때문에 ANON이 저장되지 않는다.</p>
<h1 id="typedef">typedef</h1>
<hr>
<p>typedef는 자료형이 복잡할 경우 그 자료형에 대한 alias를 지정하여 추후에 동일한 자료형을 사용할 시에 편리하게 이용할 수 있다.</p>
<pre><code class="language-dart">typedef ListOfInt = List&lt;int&gt;;

ListOfInt reverseListOfNumbers(ListOfInt list){
  var reversed = list.reversed;
  return reversed.toList(); //reversed를 하면 리턴이 리스트가 아니므로 바꿔줘야한다.
}

void main() {
  print(reverseListOfNumbers([1, 2, 3]));
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dart#0(nomad)]]></title>
            <link>https://velog.io/@jimmy_devkid/Dart0nomad</link>
            <guid>https://velog.io/@jimmy_devkid/Dart0nomad</guid>
            <pubDate>Mon, 02 Jan 2023 11:28:01 GMT</pubDate>
            <description><![CDATA[<h1 id="dartpad">dartpad</h1>
<hr>
<p>dart를 배우기 위해 따로 프로그램을 설치할 필요 없이 아래 링크에 있는 에디터를 이용하여 연습할 수 있다.
<a href="https://dartpad.dev/?">dartpad</a></p>
]]></description>
        </item>
    </channel>
</rss>