<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>orinugoori_art.log</title>
        <link>https://velog.io/</link>
        <description>오리너구리입니다</description>
        <lastBuildDate>Tue, 16 Jul 2024 12:10:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>orinugoori_art.log</title>
            <url>https://velog.velcdn.com/images/orinugoori_art/profile/f58b4727-5b81-47ea-aef6-1e34564d3d01/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. orinugoori_art.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/orinugoori_art" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[TIL 0716]]></title>
            <link>https://velog.io/@orinugoori_art/TIL-0716-cbb2xa9j</link>
            <guid>https://velog.io/@orinugoori_art/TIL-0716-cbb2xa9j</guid>
            <pubDate>Tue, 16 Jul 2024 12:10:00 GMT</pubDate>
            <description><![CDATA[<h2 id="코드카타">코드카타</h2>
<p>오늘은 58번을 풀었다..</p>
<p>소수 판별하는문제 옛날에 했었는데,,</p>
<p>거기서 좀 더,, 추가된 형식이였는데</p>
<p>정신이 안차려짐</p>
<p>흐리멍텅 멍청 짓 종내 했음~</p>
<hr>
<h2 id="스탠다드반-과제">스탠다드반 과제</h2>
<p>어제 자기전에 디테일 페이지를 만들기 위한 준비준비까지 해놓고 잤음</p>
<p>액티비티로 되어있던 페이지들 다 프래그먼트로 바꿀애들 바꿔주고..</p>
<p>디테일 페이지 기본 레이아웃 틀 만들고…</p>
<p>오늘은 디테일 페이지를 만든다….</p>
<h3 id="1-더미-데이터-파밍하기">1. 더미 데이터 파밍하기..</h3>
<p>디테일 페이지까지 만들게 될 줄 알았으면 스포티파이 안했을텐데..</p>
<p>더미데이터 긁어올 양이 너무 많아버림.ㅎㅎ</p>
<p>플레이리스트 하나 클릭할 때마다 노래 최소 10개씩은 나와야하는데;;</p>
<p>노래 최소 90개를 제목, 아티스트, 앨범아트 긁어와야함ㅎㅎ 와 신난다<del>~</del></p>
<h3 id="2-home-fragment-에-있는-리사이클러-뷰에서-클릭-이벤트-만들기">2. Home Fragment 에 있는 리사이클러 뷰에서 클릭 이벤트 만들기</h3>
<ol>
<li>클릭 이벤트 인터페이스 만들기</li>
</ol>
<pre><code class="language-kotlin">interface OnItemClick{
    fun onClick(position: Int)
}</code></pre>
<p>인터페이스 하나 기깔나게 만들어줌</p>
<ol>
<li>Adapter 클래스에서 인터페이스 객체 만들어주기</li>
</ol>
<pre><code class="language-kotlin">var itemClick : OnItemClick? = null</code></pre>
<ol>
<li>onBindViewHolder 내에서 setOnClickListener 만들어줌</li>
</ol>
<pre><code class="language-kotlin">override fun onBindViewHolder(holder: HorizontalAdapter.Holder, position: Int) {
    holder.itemView.setOnClickListener {
    itemClick?.onClick(position)
    }</code></pre>
<ol>
<li>Home 프래그먼트에서 adapter에서 2번에서 만든 인터페이스 객체 불러온다음에 정의해줌 </li>
</ol>
<pre><code class="language-kotlin">adapterRecommend.itemClick = object : OnItemClick{
    override fun onClick(position: Int) {
       val category = &quot;RecommendStation&quot;
       val index = position
       val detailInstance = Detail.newInstance(category, index)
       val transaction = parentFragmentManager.beginTransaction()
       transaction.replace(R.id.fragment_container, detailInstance)
       transaction.addToBackStack(null)
       transaction.commit()
}</code></pre>
<p>OnItemClick 인터페이스를 구현하는 오브젝트 하나 만들어준다음에, </p>
<p>내부 함수 정의.</p>
<p>해당 아이템을 클릭하면 Detail Fragment로 전환하면서 데이터도 보내줘야해서</p>
<p>넣어줄 변수 만들어주고, Detail Fragment 의 newInstance 생성해서 넣어줌</p>
<ol>
<li>Datail 프래그먼트에서 데이터 받게 해주기</li>
</ol>
<pre><code class="language-kotlin">    companion object {
        @JvmStatic
        fun newInstance(param1: String, param2 : Int) =
            Detail().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putInt(ARG_PARAM2, param2)
                }
            }
    }</code></pre>
<p>프래그먼트 만들면 맨 밑에 짱박혀있는 컴패니언 오브젝트의 new Instance 함수의 파라미터를 내가 보낸 정보에 맞게 고쳐줌</p>
<pre><code class="language-kotlin">class Detail : Fragment() {
    private var param1: String? = null
    private var param2: Int? = null</code></pre>
<p>여기도 고쳐줌</p>
<h3 id="3-클릭했을-때-불러올-detail-fragment-안에-recycler-view-넣어주기">3. 클릭했을 때 불러올 Detail Fragment 안에 Recycler View 넣어주기</h3>
<p>이게 진짜 미친놈임</p>
<p>이거하면서 진짜 처음으로 하차하고싶어짐</p>
<p>스탠다드반 수준별 수업 자료랑 희영튜터님이 주신 깃 허브 자료 보면서 참고해서 만들려고 했는데</p>
<p>생각대로 안되어버림.</p>
<p>사실 어려운 이유는 첫단추 잘못껴서그럼</p>
<p>애초에 메인에서 만들 때 데이터클래스 하나에 짬뽕으로 다 쳐넣고 처리하려고 이것저것 시도해서 어떻게든 만들어놨는데 이게 오늘도 발목잡아버림</p>
<p>처음에는 List Adapter랑 SealedClass써서 만들려고했는데</p>
<p>맘대로 안되어버림..</p>
<p>내가 완벽하게 이 리사이클러뷰와 리스트 어댑터뷰의 모든 함수를 꿰고있고, DiffUtil 도 꿰고있고</p>
<p>Enum클래스 Sealed 클래스 꿰고있고 한 상태면 상관 없었을텐데 지금 거의 말하는 감자 상태로</p>
<p>자료 보면서 하나하나 이해해봐야되는데 응용까지 해야되니까</p>
<p>선행학습 안하고 학교에서만 수학 배우는 애가 오늘 학교 수학시간에 뭐 하나 배웠는데 수학익힘책 문제도 다 안푼 상태로 갑자기 집와서 쎈 인가 그 무슨 응용문제 있는 문제집 풀려고 머리 쥐어뜯는 꼴이였음</p>
<p>근데 또 내일 까지 제출이니까 막 하나하나 뜯어서 볼 시간도 없는 것 같고 걍 하차해버리고싶었다.</p>
<p>진짜 이거는 트러블 슈팅 기록하면서 했으면 나중에 엄청 도움됐을텐데 하면서 멘탈나가서 하나도 안적고 그냥 해버림 ㅎ.ㅎ </p>
<p>하지만 하차 한다고 매니저님 한테 안달려간것만으로도 내 자신이 기특하다. 쏘 독해<del>like 르쎄라핌</del>잊지마 내가 두고온 케리아…(코딩 공부한다고 lck 못 챙겨본다는 뜻)</p>
<p>결국 완벽하겐 구현 못하고 그냥 되는대로 구현했음</p>
<p>내가 구현하고 싶었던 건 원래</p>
<p>홈에서 리사이클러뷰 아이템 (플레이리스트) 한개 누르면, 해당 플레이리스트의 음악들이 쫙 나오고,</p>
<p>밑에 다른 리사이클러 뷰에는 다른 추천항목으로 다른 카테고리의 플레이리스트가 나오게 하고싶었는데,</p>
<p>내가 구현한건 아이템 누르면, 해당 플레이리스트의 음악 나오기까지는 성공했는데, </p>
<p>다른 추천 항목에 다른 카테고리가아니고 그냥 같은 카테고리의 플레이리스트들이 나온다^^발</p>
<p>일단 내 TIL은 그냥 쓰라고 해서 쓰는거고 혹시 인터넷이 지속되는 많은 기간동안 운없게도 멀티뷰 리사이클러에 대한 정보를 찾다가 이 글을 발견해서 참고해볼까? 하고 보는 사람이 없길 바람. 개 엉터리임니다</p>
<p>내가 이 거지같은 구현을 어떻게 했냐면.</p>
<ol>
<li><p>뷰타입을 나타낼 Enum class를 만들어줌</p>
<pre><code class="language-kotlin"> enum class MultiViewEnum(val viewType: Int) {
     SONG(0),
     RECOMMEND(1)
 }</code></pre>
<p> SONG은 0  RECOMMEND는 1을 할당해줬다.</p>
</li>
</ol>
<ol>
<li><p>데이터 클래스도 하나 새로 만들어줌</p>
<pre><code class="language-kotlin"> data class PlaySongList(
     val viewType : MultiViewEnum,
     val playList : MutableList&lt;PlayList&gt;,
     val SongList : MutableList&lt;Song&gt;,
     val anotherPlayList : MutableList&lt;PlayList&gt;
 )</code></pre>
<p> 첫번째로 1번에서 만든 EnumClass로 뷰타입을 받아주고,</p>
<p> 나머지는 내가 사용할 데이터들을 넣어줌</p>
</li>
</ol>
<ol>
<li><p>Adapter 정의</p>
<pre><code class="language-kotlin"> class SongAdapter(private val items: PlaySongList) :
     RecyclerView.Adapter&lt;RecyclerView.ViewHolder&gt;() {

     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
         return when (viewType) {
             MultiViewEnum.SONG.viewType -&gt; {
                 val binding =
                     SongHolderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                 SongHolder(binding)
             }

             MultiViewEnum.RECOMMEND.viewType -&gt; {
                 val binding = RecommendHolderBinding.inflate(
                     LayoutInflater.from(parent.context),
                     parent,
                     false
                 )
                 RecommendHolder(binding)
             }

             else -&gt; throw IllegalArgumentException(&quot;Invalid view type&quot;)
         }
     }

     override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

         when (holder) {
             is SongHolder -&gt; {
                 holder.bind(items.SongList[position])
             }

             is RecommendHolder -&gt; {
                 holder.bind(items.playList[position])
             }
         }
     }

     override fun getItemViewType(position: Int): Int {
         return items.viewType.viewType
     }

     override fun getItemCount(): Int {
         return if(items.viewType == MultiViewEnum.SONG){
             items.SongList.size
         }else{
             items.playList.size
         }
     }
 }

 class SongHolder(private val binding: SongHolderBinding) : RecyclerView.ViewHolder(binding.root) {
     fun bind(song: Song) {
             binding.apply {
                 ivSongCover.setImageResource(song.cover)
                 tvSongName.text = song.song
                 tvArtistName.text = song.artist
             }
         }
     }

 class RecommendHolder(private val binding: RecommendHolderBinding) :
     RecyclerView.ViewHolder(binding.root) {
     fun bind(item: PlayList) {
         binding.apply {
             ivCoverPlayList.setImageResource(item.cover)
             tvPlaylistName.text = item.playlistName
             tvPlaylistDesc.text = item.desc
         }

     }
 }</code></pre>
<p> RecyclerView.Adapter를 구현하는 SongAdapter라는걸 만들어줌 </p>
<p> 지금 생각하니까 이름 DetailAdapter로 할껄잘못만든거같음</p>
<p> 홀더도 정의해줌</p>
<p> 마찬가지로 RecyclerView의 ViewHolder를 갖다가 구현하는데</p>
<p> 인자로 binding 받는다고 해놓고 RecyclerView.ViewHolder()안에 binding.root 넣어주면 </p>
<p> 내가 정의해놓은 holder의 xml파일에서 binding으로 객체를 가져올 수있음</p>
<p> bind라는 함수를 사용해서 여기에서 사용할 데이터 타입 정해서</p>
<p> 각 뷰에 맞춰서 적용해줌</p>
<p> Song Holder는 Song 타입의 데이터를 사용하고,</p>
<p> RecommendHolder는 PlayList 타입의 데이터를 사용함</p>
<p> 그리고 onCreateViewHolder, onBindViewHolder, getItemViewType, getItemCount 를 구현해줌</p>
<p> onCreateViewHolder에서는 </p>
<p> return when을 사용해서 EnumClass에서 정해준 viewType 에 따라서 다른 레이아웃을 뿌려주게? 만들어줌</p>
<p> onBindViewHolder에서는 </p>
<p> when으로 holder에 따라서 holder가 SongHolder면 holder에 bind로 받은 item의 SongList에서 position을 참고해서 넣어주고</p>
<p> RecommendHolder면 playList에서 넣어줌</p>
<p> getItemViewType에서는 items에서 viewType을 참고해서 viewType을 반환해주면됨</p>
<p> 21세기나 됐으면 이런건 좀 알아서해라 내가 정의안해줘도 ㅋㅋ 고철덩어리같은것.</p>
<p> getItemCount에서는 return if 로  item의 뷰타입이 SONG이면 SongList의 사이즈를, 아니면 playList의 사이즈를 반환하게 해줌</p>
</li>
<li><p>Detail Fragment에서 리사이클러 뷰에 어댑터 연결해주기</p>
<pre><code class="language-kotlin"> val playList = MyPlayListObject.recommendStation.getOrNull(index)
 val songData = playList?.song ?: mutableListOf()

 val songListData = PlaySongList(MultiViewEnum.SONG, MyPlayListObject.recommendStation,songData,MyPlayListObject.mixForUser)
 val recommendData = PlaySongList(MultiViewEnum.RECOMMEND, MyPlayListObject.recommendStation,SongListObject.hyang,MyPlayListObject.mixForUser)

 binding.rvSongList.adapter = SongAdapter(songListData)
 binding.rvSongList.addItemDecoration(RecyclerDecoration(16,16,16,16))

 binding.rvRecommend.adapter = SongAdapter(recommendData)
 binding.rvRecommend.layoutManager = GridLayoutManager(this.context,2)
 binding.rvRecommend.addItemDecoration(RecyclerDecoration(16,16,16,16))</code></pre>
<p> 위에서 Adapter에 PlaySongList라는 타입을 먹여주기로 약속했는데</p>
<p> PlaySongList는 viewType과 PlayList, Song 타입의 MutableList를 받는 애임</p>
<p> playList라는 변수에 Dataclass에서 정의해둔 object하나 꺼내와서 거기에 Home 에서 받아온 position을 넘김 왜 이름을 index로 지었냐면 나도 후회중임 가독성 ㅎㅌㅊ</p>
<p> 그리고 songData라는애는 playList의 song을 넣어줌</p>
<p> 그래서 각 rvSongList adpater에 쑤셔넣은 정보들을 넣어줌!</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 58 (모의고사)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-58-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-6tcbouhl</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-58-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-6tcbouhl</guid>
            <pubDate>Tue, 16 Jul 2024 12:09:20 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>주어진 숫자 중 3개의 수를 더했을 때 소수가 되는 경우의 개수를 구하려고 합니다. 숫자들이 들어있는 배열 nums가 매개변수로 주어질 때, nums에 있는 숫자들 중 서로 다른 3개를 골라 더했을 때 소수가 되는 경우의 개수를 return 하도록 solution 함수를 완성해주세요.</p>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>nums에 들어있는 숫자의 개수는 3개 이상 50개 이하입니다.</li>
<li>nums의 각 원소는 1 이상 1,000 이하의 자연수이며, 중복된 숫자가 들어있지 않습니다.</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<pre><code class="language-kotlin">import kotlin.math.*

class Solution {
    fun solution(nums: IntArray): Int {
        var answer = 0

        for(i in 0 until nums.size-2){
            for(j in i+1 until nums.size-1){
                for(k in j+1 until nums.size){
                    var isPrime = true
                    val newNum = nums[i]+nums[j]+nums[k]
                    val sqrt = Math.sqrt(newNum.toDouble()).toInt()
                    for(l in 2 .. sqrt){
                        if(newNum % l == 0){
                            isPrime = false
                            break 
                        }
                    }
                    if(isPrime){
                        answer += 1
                    }

                }    

                }
            }
        return answer
        }


    }
</code></pre>
<p>하 .. 수학이 싫당..</p>
<p>처음에 안풀려서 보니까 또 문제 제대로안읽어서..</p>
<p>인덱스 시작 다 0부터 시작하면 안되는데,, 다 0부터 시작해서 중복되고있었음..</p>
<p>근데 그러고도 안돼서 뭐지 했는데 나머지연산자 써야될 곳에 나누기 연산자 써서 그랬음..</p>
<p>걍 정신 못차림</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 0715]]></title>
            <link>https://velog.io/@orinugoori_art/TIL-0715-ibaxa60h</link>
            <guid>https://velog.io/@orinugoori_art/TIL-0715-ibaxa60h</guid>
            <pubDate>Mon, 15 Jul 2024 11:49:51 GMT</pubDate>
            <description><![CDATA[<h2 id="코드카타">코드카타</h2>
<p><a href="https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-57-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-nvjg7e22">https://velog.io/@orinugoori_art/알고리즘-CODEKATA-57-모의고사-nvjg7e22</a></p>
<p>오늘 문제는 모드연산자를 쓰는 방법을 생각 못해버려서 도저히 못풀겠어서 다른 사람 풀이 참고해서 풀었음..
수학적인 사고는 언제나 벽이구만</p>
<hr>
<h2 id="당근-마켓-과제">당근 마켓 과제</h2>
<p>주말에 까먹고 빼먹은 알림 구현을 했당.</p>
<p>강의 들었던거 다시 듣고 강의 자료 보면서 구현하는거 자체는 성공했는데</p>
<p>강의 자료 없이는 다시 만들라고해도 기억안날 거 같고</p>
<p>다른 사람한테 설명 할 수 있나? 하면 그것도 제대로 못 할 것같음..</p>
<p>스탠다드반 과제가 급해서 일단은 그냥 완성은 했는데,</p>
<p>스탠다드반 과제 다 끝내고 강의내용 중에 아직 제대로 이해 못한 부분이나 부족한 부분은 다시 정리하면서 이해해야함</p>
<hr>
<h2 id="스탠다드반-과제">스탠다드반 과제</h2>
<p>저번 과제였던 클론 코딩 프로젝트에 이번에 배운 리사이클러 뷰를 적용시키고,</p>
<p>아이템 클릭시 상세페이지 까지 구현해야함!</p>
<p>오늘은 일단 메인 페이지에 있는 애들을 리사이클러 뷰로 대체 해주는 것 까지 완료했다.</p>
<p>다른건 강의에서 다 배운 거 였는데, 아이템 간격을 조정하는 부분과 레이아웃 매니저를 LinearLayout 말고 다른 레이아웃 매니저를 사용하는 방법은 안배워서 그 부분을 조금 더 공부했음</p>
<h3 id="grid-layout-manager-사용하기">Grid Layout Manager 사용하기</h3>
<p>MainActivity.kt</p>
<pre><code class="language-kotlin">binding.rvRecentPlaylist.adapter = adapterRecent
binding.rvRecentPlaylist.layoutManager = GridLayoutManager(this,2)
binding.rvRecentPlaylist.addItemDecoration(recentPlayDecoration)</code></pre>
<p>이렇게 layoutManager를 할당해줄 때 그 동안은 LinearLayout만 사용했는데 이번에는 그리드를 써야할 것 같아서  GridLayoutManager를 씀 </p>
<p>방법은 짱 간단. 그냥 ()안에 this,랑 그리드 몇 행으로 만들건지 숫자 써주면됨</p>
<h3 id="custom-item-decoration-정의하기">Custom Item Decoration 정의하기</h3>
<p>리사이클러 뷰를 쓰면서 지금까지는 아이템 사이의 간격을 따로 정의할 일이 없었는데 </p>
<p>스포티파이 앱은 아이템 사이가 띄워져있어서 ItemDecoration에 대해 찾아서 구현했다.</p>
<p>RecyclerDecoration.kt</p>
<pre><code class="language-kotlin">class RecyclerDecoration(
    private val topSpace : Int,
    private val startSpace : Int,
    private val endSpace : Int,
    private val bottomSpace : Int) : RecyclerView.ItemDecoration() {
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)

        val position = parent.getChildLayoutPosition(view)
        val count = state.itemCount

        outRect.left = startSpace
        outRect.right = endSpace
        outRect.bottom = bottomSpace

        if(parent.getChildAdapterPosition(view)== 0){
            outRect.top= topSpace
        }

    }
}</code></pre>
<ol>
<li>클래스 하나 파서 이름 대충 그럴싸하게 지어주고, RecyclerView의 ItemDecoration을 상속해줌</li>
<li>나는 아이템 사이 간격만 필요해서 getItemOffsets 함수만 오버라이드해서 구현해줌</li>
<li>재사용을 위해서 함수에 top bottom start end 값을 각각 받게 해줌</li>
<li>outRect.방향 에 받은 값들을 적용해줌</li>
</ol>
<p>MainActivity.kt</p>
<pre><code class="language-kotlin">val recentPlayDecoration = RecyclerDecoration(16,16,16,16)
val horizontalDecoration = RecyclerDecoration(0,0,40,0)

binding.rvRecentPlaylist.addItemDecoration(recentPlayDecoration)
binding.rvRecommendStation.addItemDecoration(horizontalDecoration)</code></pre>
<p>이런식으로 적용할 때 변수하나 만들어서 객체로 만들어주고, 적용할 리사이클러뷰에 addItemDecoration으로 적용해준다.</p>
<hr>
<h2 id="tmi">TMI</h2>
<p>팀 프로젝트 때부터 바빠져서 TIL 따로 안올리고있었는데
순회시간에 매니저님이 저격해주심히히히
그래서 오늘은 귀찮지만 TIL을 대충 써왔당~</p>
<p>숙련주차되니까 진짜 너무 정신 없어버림
강의 듣고 다 이해하려면 하나하나 알아볼게 너무 많아서 공부할 게 많고,,, 거기에,, 과제도 많고,,,
주말까지 나와서 과제했는데도 이정도!!!!
주말에 공부안하시는분들은..어떻게 따라가는걸까?
내가 빡대가리인거같기도?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 57 (모의고사)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-57-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-nvjg7e22</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-57-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-nvjg7e22</guid>
            <pubDate>Mon, 15 Jul 2024 11:30:24 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.</p>
<p>1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...</p>
<p>2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...</p>
<p>3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...</p>
<p>1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.</p>
<h3 id="제한-조건">제한 조건</h3>
<ul>
<li>시험은 최대 10,000 문제로 구성되어있습니다.</li>
<li>문제의 정답은 1, 2, 3, 4, 5중 하나입니다.</li>
<li>가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(answers: IntArray): IntArray {
        var answer = intArrayOf()

        val personA = listOf(1,2,3,4,5)
        val personB = listOf(2,1,2,3,2,4,2,5)
        val personC = listOf(3,3,1,1,2,2,4,4,5,5)

        var count = 0

        var scoreA : Int = 0
        var scoreB : Int = 0
        var scoreC : Int = 0

        answers.forEach{
            if(it == personA[count % personA.size]) scoreA++
            if(it == personB[count % personB.size]) scoreB++
            if(it == personC[count % personC.size]) scoreC++
            count++       
        }


    if(scoreA &gt;=scoreB &amp;&amp; scoreA &gt;=scoreC){
        answer += 1
    }
    if(scoreB &gt;= scoreA &amp;&amp; scoreB &gt;= scoreC){
        answer += 2
    }
    if(scoreC &gt;= scoreA &amp;&amp; scoreC &gt;= scoreB){
        answer += 3
    }

        return answer
    }
}</code></pre>
<p>으어 오늘거 어려워서 다른사람 풀이 검색해서 보고 참고해서 풀었음..
나머지 연산자 써서 식 짤 생각을 못했당..ㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 56 (과일 장수)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-56-%EA%B3%BC%EC%9D%BC-%EC%9E%A5%EC%88%98-ouwk40zc</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-56-%EA%B3%BC%EC%9D%BC-%EC%9E%A5%EC%88%98-ouwk40zc</guid>
            <pubDate>Mon, 15 Jul 2024 11:29:00 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>과일 장수가 사과 상자를 포장하고 있습니다. 사과는 상태에 따라 1점부터 k점까지의 점수로 분류하며, k점이 최상품의 사과이고 1점이 최하품의 사과입니다. 사과 한 상자의 가격은 다음과 같이 결정됩니다.</p>
<ul>
<li>한 상자에 사과를 m개씩 담아 포장합니다.</li>
<li>상자에 담긴 사과 중 가장 낮은 점수가 p (1 ≤ p ≤ k)점인 경우, 사과 한 상자의 가격은 p * m 입니다.</li>
</ul>
<p>과일 장수가 가능한 많은 사과를 팔았을 때, 얻을 수 있는 최대 이익을 계산하고자 합니다.(사과는 상자 단위로만 판매하며, 남는 사과는 버립니다)</p>
<p>예를 들어, <code>k</code> = 3, <code>m</code> = 4, 사과 7개의 점수가 [1, 2, 3, 1, 2, 3, 1]이라면, 다음과 같이 [2, 3, 2, 3]으로 구성된 사과 상자 1개를 만들어 판매하여 최대 이익을 얻을 수 있습니다.</p>
<ul>
<li>(최저 사과 점수) x (한 상자에 담긴 사과 개수) x (상자의 개수) = 2 x 4 x 1 = 8</li>
</ul>
<p>사과의 최대 점수 <code>k</code>, 한 상자에 들어가는 사과의 수 <code>m</code>, 사과들의 점수 <code>score</code>가 주어졌을 때, 과일 장수가 얻을 수 있는 최대 이익을 return하는 solution 함수를 완성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>3 ≤ <code>k</code> ≤ 9</li>
<li>3 ≤ <code>m</code> ≤ 10</li>
<li>7 ≤ <code>score</code>의 길이 ≤ 1,000,000<ul>
<li>1 ≤ <code>score[i]</code> ≤ k</li>
</ul>
</li>
<li>이익이 발생하지 않는 경우에는 0을 return 해주세요.</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(k: Int, m: Int, score: IntArray): Int {
        var answer: Int = 0

        var sortedScore = score.sortedDescending()

        //m개씩 끊어서, 제일작은값 * m
        sortedScore.chunked(m).forEach{
            if(it.size == m){
                answer += it.minOrNull()!! * m
            }
        }
        return answer
    }
}</code></pre>
<p>받은 점수 배열을 개수별로 끊는게 뭔가 있을 거같은데 모르겠어서 찾아봤더니</p>
<p>chunked라는 애가 있었당!</p>
<p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/chunked.html">https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/chunked.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 55 (카드 뭉치)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-55-%EC%B9%B4%EB%93%9C-%EB%AD%89%EC%B9%98</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-55-%EC%B9%B4%EB%93%9C-%EB%AD%89%EC%B9%98</guid>
            <pubDate>Mon, 15 Jul 2024 11:28:21 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.</p>
<ul>
<li>원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.</li>
<li>한 번 사용한 카드는 다시 사용할 수 없습니다.</li>
<li>카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.</li>
<li>기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.</li>
</ul>
<p>예를 들어 첫 번째 카드 뭉치에 순서대로 [&quot;i&quot;, &quot;drink&quot;, &quot;water&quot;], 두 번째 카드 뭉치에 순서대로 [&quot;want&quot;, &quot;to&quot;]가 적혀있을 때 [&quot;i&quot;, &quot;want&quot;, &quot;to&quot;, &quot;drink&quot;, &quot;water&quot;] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 &quot;i&quot;를 사용한 후 두 번째 카드 뭉치에서 &quot;want&quot;와 &quot;to&quot;를 사용하고 첫 번째 카드뭉치에 &quot;drink&quot;와 &quot;water&quot;를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.</p>
<p>문자열로 이루어진 배열 <code>cards1</code>, <code>cards2</code>와 원하는 단어 배열 <code>goal</code>이 매개변수로 주어질 때, <code>cards1</code>과 <code>cards2</code>에 적힌 단어들로 <code>goal</code>를 만들 있다면 &quot;Yes&quot;를, 만들 수 없다면 &quot;No&quot;를 return하는 solution 함수를 완성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>1 ≤ <code>cards1</code>의 길이, <code>cards2</code>의 길이 ≤ 10<ul>
<li>1 ≤ <code>cards1[i]</code>의 길이, <code>cards2[i]</code>의 길이 ≤ 10</li>
<li><code>cards1</code>과 <code>cards2</code>에는 서로 다른 단어만 존재합니다.</li>
</ul>
</li>
<li>2 ≤ <code>goal</code>의 길이 ≤ <code>cards1</code>의 길이 + <code>cards2</code>의 길이<ul>
<li>1 ≤ <code>goal[i]</code>의 길이 ≤ 10</li>
<li><code>goal</code>의 원소는 <code>cards1</code>과 <code>cards2</code>의 원소들로만 이루어져 있습니다.</li>
</ul>
</li>
<li><code>cards1</code>, <code>cards2</code>, <code>goal</code>의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다.</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(cards1: Array&lt;String&gt;, cards2: Array&lt;String&gt;, goal: Array&lt;String&gt;): String {
        var count1 = 0
        var count2 = 0

        for(v in goal){
            if (count1 &lt; cards1.size &amp;&amp; v == cards1[count1]){
                count1++
            }else if(count2 &lt; cards2.size &amp;&amp; v == cards2[count2]){
                count2++
            }else{
                return &quot;No&quot;
            }      
        }

        return &quot;Yes&quot;
    }
}</code></pre>
<p>이렇게 풀라고 낸 문제가 맞나?</p>
<p>몰?루~</p>
<p>그래도 그 걸린 시간? 도 0.02ms 정도면 ㄱㅊ은거아닌가??</p>
<hr>
<h3 id="다른-사람-풀이">다른 사람 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(cards1: Array&lt;String&gt;, cards2: Array&lt;String&gt;, goal: Array&lt;String&gt;): String {
        var idx1 = 0
        var idx2 = 0
        goal.forEach {
            if (idx1 &lt; cards1.size &amp;&amp; it == cards1[idx1]) idx1++
            else if (idx2 &lt; cards2.size &amp;&amp; it == cards2[idx2]) idx2++
            else return &quot;No&quot;
        }
        return &quot;Yes&quot;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 54 (2016)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-54-2016-xa45n201</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-54-2016-xa45n201</guid>
            <pubDate>Mon, 15 Jul 2024 11:27:28 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각 <code>SUN,MON,TUE,WED,THU,FRI,SAT</code></p>
<p>입니다. 예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 &quot;TUE&quot;를 반환하세요.</p>
<h3 id="제한-조건">제한 조건</h3>
<ul>
<li>2016년은 윤년입니다.</li>
<li>2016년 a월 b일은 실제로 있는 날입니다. (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다)</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<p><strong>최종 코드</strong></p>
<pre><code class="language-kotlin">class Solution {
    fun solution(a: Int, b: Int): String {
        var answer = &quot;&quot;
        var dayList = listOf&lt;String&gt;(&quot;FRI&quot;,&quot;SAT&quot;,&quot;SUN&quot;,&quot;MON&quot;,&quot;TUE&quot;,&quot;WED&quot;,&quot;THU&quot;)

        //1월 31, 2월 29, 3월 31, 4월 30, 5월 31, 6월 30, 7월 31, 8월 31, 9월 30, 10월 31, 11월 30, 12월 31

        var monthPlus = listOf&lt;Int&gt;(0,3,4,0,2,5,0,3,6,1,4,6)
        val calculate = ((b-1) % 7 + monthPlus[a-1])%7
        answer=dayList[calculate]

        return answer

    }
}</code></pre>
<p>하 오늘 너무 귀찮았다..</p>
<p>너무 오랜만에 코드카타 해서 그런가..</p>
<p>아니면 그냥 수학적으로 접근해서 푸는거 원래 어려워해서 그런가</p>
<p>요일 구하는 공식도 따로 있는데, 찾아서 봐도 뭔말인지 정확히 이해안되고..</p>
<p>나는 년도 상관없이 16년도 내에서의 요일만 구하면되는데…</p>
<p>아주 비효율 적이고 이런 방식을 원한 문제가 아닐 것 같지만.. 그냥 되는대로 풀어버림.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 0709~0714]]></title>
            <link>https://velog.io/@orinugoori_art/TIL-0709</link>
            <guid>https://velog.io/@orinugoori_art/TIL-0709</guid>
            <pubDate>Mon, 15 Jul 2024 11:22:46 GMT</pubDate>
            <description><![CDATA[<p>안드로이드 숙련주차 제공 강의 학습</p>
<ul>
<li>데이터 바인딩 공부하기&lt; 실무 필수적으로 쓰지는 않아서</li>
</ul>
<h2 id="1-view-binding">1. View binding</h2>
<ul>
<li><p>find VIew By Id를 대체하는 코드</p>
</li>
<li><p>모듈에서 viewBinding을 설정하면 각 모듈에 있는 xml 레이아웃 파일의 결합 클래스를 생성함</p>
</li>
<li><p>binding 클래스의 인스턴스에는 상응하는 레이아웃에 ID가 있는 모든 뷰의 직접 참조가 포함된다.</p>
</li>
</ul>
<p>findViewById와의 차이점</p>
<ol>
<li>Null safety<ul>
<li>뷰바인딩은 직접 참조를 생성하므로 유효하지 않은 view ID로 인한 null예외가 발생하지 않는다.</li>
</ul>
</li>
<li>Type safety<ul>
<li>타입이 맞지 않아 발생하는 오류를 방지할 수 있음</li>
</ul>
</li>
</ol>
<p>사용법</p>
<ol>
<li>build 모듈 파일에 buildFeatures 안에 viewBinding = true 적어줌</li>
<li>전역 변수로 binding 지연초기화로 만들어주고</li>
<li>onCreate 안에서 binding 초기화 해줌</li>
</ol>
<pre><code class="language-kotlin">private lateinit var binding : ActivityMainBinding

override fun onCreate(savedInstanceState : Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
}</code></pre>
<ol>
<li>binding.가져올애아이디 로 접근해서 사용가능</li>
</ol>
<p>*주의사항</p>
<p>ViewBinding은 자동으로 결합 클래스를 생성하는데, 해당 객체의 이름은 레이아웃 이름에 Binding을 붙여서 만들어짐</p>
<p>Ex)  activity_main.xml → ActivityMainBinding</p>
<p>fragment_home.xml → FragmentHomeBinding</p>
<p>궁금한 점</p>
<ol>
<li><p>findViewById 보다 안정성이 높고 간단한 코드인데 처음부터 뷰바인딩을 안하고 처음에는 findViewById 방식을 먼저 배우는 이유?</p>
<p> 그냥 원래 findViewById 방식이 원래 있던 방식이고ViewBinding이 비교적 최신? 기술이라서 그 .. 코딩 역사..?인 이유로 전부 이해해야하기때문인지? </p>
<p> 아니면 findViewById 방식을 사용해보면서 먼저 내가 가져오려는 객체가 어떤타입인지 인지하고 가져다 쓰는 연습을 위한거였는지? </p>
<p> 아니면 따로 내가 생각하지 못한 이유가 있는지!?</p>
<p> → 튜터님 답변 : 뷰 바인딩이 최신 기술이라서 혼자서 구글링하면서 다른 사람 코드를 참고할 때findViewById를 사용한 방식의 코드를 봐야할 수 도 있는데, 그 때 이해를 할 수 있어야하기 때문에 그렇다! </p>
<p> 둘 다 익숙하게 하기위해서 처음에는 옛날방식인 findViewById를 배워서 사용해봤고, 이제부터는 ViewBinding를 사용할것~ </p>
</li>
<li><p>Type safety </p>
<p> 이미지 뷰(ImageView)에 텍스트를 설정하려고 하면 오류가 발생할 텐데, 뷰 바인딩을 사용하면 이런 실수를 할 가능성이 없어집니다. 즉, 이미지 뷰는 이미지 뷰로, 텍스트 뷰는 텍스트 뷰로만 사용되게 하여, 잘못된 타입 사용으로 인한 오류가 발생하지 않도록 보장합니다. </p>
<p> 이 부분이 이해가 안댄다!</p>
<p> 어차피 findViewById를 사용해도 &lt;&gt;안에 타입 잘못 쓰면 오류로 안가져와지는게 아닌가!?</p>
<p> 아니면 imageView에 . 찍고 텍스트뷰의 속성 적어도 안뜨지 않았나!?!?!?! </p>
<p> → 튜터님 답변 :  안드로이드 스튜디오 업데이트로 이제는 타입 잘못적을 때 빨간줄이 뜨지만 옛날에는 안떴다! </p>
<p> 그래도 코드가 복잡해지다보면 휴먼에러가 발생할수도 있기때문에 타입 세이프티는 뷰 바인딩의 장점이 될 수 있을듯!</p>
</li>
</ol>
<h2 id="2-adapter-view">2. Adapter View</h2>
<p>ViewGroup을 상속하는 추상클래스.</p>
<p>여러개의 항목을 나열하고 선택할 수 있는 기능을 제공하는 뷰</p>
<p>대용량의 데이터 세트를 효율적으로 표시할 수 있게 하는 것이 주 목적</p>
<p>ListVIew(수직 나열)와 GridView(격자 형태 나열), Spinner(드롭다운리스트?) 등이있음</p>
<p>Adapter View를 사용하기 위해 필요한 요소 3가지</p>
<ol>
<li>Data (빔프로젝터안에 넣은 영화 폴더)</li>
<li>Adapter (빔프로젝터)</li>
<li>AdapterView (빔 프로젝트 스크린?)</li>
</ol>
<p>Adapter</p>
<ul>
<li>데이터를 관리하며 데이터 원본과 어댑터 뷰 사이의 중계 역할을하는 인터페이스</li>
<li>AdapterView 에서 Adapter의 getCount() 메서드를 통해서 어댑터가 관리하는 데이터 항목의 총 개수 반환</li>
<li>AdapterView 에서 Adapter의 getView() 메서드를 통해서 화면에 실제로 표시할 항목 뷰를 얻고, 표시함</li>
</ul>
<p>어댑터 인터페이스를 상속하는 어댑터 클래스들.</p>
<p>Adapter 종류</p>
<ol>
<li>BaseAdapter</li>
<li>ArrayAdapter<ul>
<li>List</li>
</ul>
</li>
<li>CursorAdapter<ul>
<li>Data Base</li>
</ul>
</li>
<li>SimpleAdapter</li>
</ol>
<p>ArrayAdapter 객체 생성하는 방법</p>
<ul>
<li>ArrayAdapter(context : Context , resource : Int, textViewResourceId : Int, objects : T&lt;&gt;)</li>
<li>→ ArrayAdapter(컨텍스트,</li>
</ul>
<p>ListView</p>
<ul>
<li>AdapterView의 대표 위젯</li>
<li>여러 항목을 수직으로 나열하여 표시</li>
</ul>
<p>GridView</p>
<ul>
<li>AdapterView의 대표 위젯 2</li>
<li>여러 항목을 2차원 스크롤 가능한 그리드에 표시</li>
</ul>
<p>궁금한점</p>
<ol>
<li><p>ListView 만들어보니까 알아서 스크롤이 가능한데 스크롤뷰를 상속받고있는지 알아보기 , 스크롤외의 뭐 어떻게 구성되어있는데 이렇게 되는건지 궁금함</p>
<p> → ListView는 AdapterView 의 하위클래스, ScrollView는 ViewGroup의 하위클래스. 따로 연관이 있지는 않은듯.</p>
</li>
<li><p>ListView는 LinearLayout 또는 다른 레이아웃의 자식뷰로 들어가야하는지</p>
<p> → 꼭 그럴필요 없다.</p>
</li>
<li><p>ArrayAdapter 생성할 때 리소스 ID는 완전 정해져있는건지? 커스텀(가능한지) </p>
</li>
<li><p>android.R.layout.simple_list_item_3 하면 세개의 텍스트 뷰로 구성된 레이아웃 이 되는건지?</p>
<p> → 얘네가 그 안드로이드 SDK에서 제공하는 기본적인 레이아웃리소스? 인데 얘네 종류가 얼마나되는지 뭐 어떤식으로 구성되어있는지를 문서에서 찾을 수가 없음 어떻게 찾아야될지 여쭤보기</p>
<p> → 태영님이 찾아주셔서 공부완료</p>
</li>
<li><p>ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) 에서는 컨텍스트, 리소스, 텍스트뷰리소스아이디, 데이터배열 이렇게 4개 같은데 생성 예제보면 왜 컨텍스트, 리소스아이디, 데이터배열 세개만 들어가지?!</p>
<p> → 공식문서 들어가서 확인해보니까 여러가지 생성자를 제공함</p>
</li>
</ol>
<p>더 알아볼 부분</p>
<ol>
<li><p>그리드 뷰 속성 각각 어떻게 적용하는지 다 이해하기</p>
<ol>
<li>columnWidth</li>
<li>numcolumns</li>
<li>VerticalSpacing</li>
<li>stretchMode</li>
</ol>
</li>
<li><p>position의 정확한 정의?</p>
<p> → item의 인덱스? </p>
<p> → 그럼 왜 굳이 index라고 안하고 position이라고 부름?</p>
<p> →</p>
</li>
<li><p>layoutParams 가 뭔지 찾아보기</p>
</li>
</ol>
<p>오늘 할일</p>
<ul>
<li>코드카타 56번</li>
<li>숙련주차 강의 끝까지 듣기</li>
</ul>
<hr>
<p>코드카타</p>
<p>잘 풀었다</p>
<p>chunked라는 함수를 배웠당</p>
<hr>
<h2 id="숙련주차-강의">숙련주차 강의</h2>
<h3 id="fragment">Fragment</h3>
<p>액티비티 위에서 동작하는 모듈화된 UI</p>
<p><strong>Framgment 생명주기</strong></p>
<p>액티비티의 생명주기와 비슷한데 액티비티와 연결 관련된 생명주기가 더 추가된 느낌</p>
<ol>
<li><strong>onAttach()</strong></li>
<li>onCreate()</li>
<li><strong>onCreateView()</strong></li>
<li><strong>onActivityCreated()</strong></li>
<li>onStart()</li>
<li>onResume()</li>
<li>onPause()</li>
<li>onStop()</li>
<li><strong>onDestroyView()</strong></li>
<li>onDestroy()</li>
<li><strong>onDetach()</strong></li>
</ol>
<p>Fragment를 액티비티에 추가하는 방법</p>
<ol>
<li>액티비티 xml 파일에 <fragment> 태그 만들어주고 크기, 배치 지정, android:name 사용해서 인스턴스화할 Fragment 클래스 지정</li>
<li>액티비티 kt 파일에서 supportFragmentManager 사용해서 프래그먼트 추가</li>
</ol>
<ul>
<li><p>supportFragmentManager</p>
<pre><code class="language-kotlin">  supportFragmentManager.commit {
              replace(R.id.frameLayout, frag)
              setReorderingAllowed(true)
              addToBackStack(&quot;&quot;)
          }</code></pre>
<ul>
<li>supportFragmentManager : 사용자 상호작용에 응답해 Fragment를 추가하거나 삭제하는 등의 작업을 하게 해주는 도구</li>
<li>replace : 어느 프레임 레이아웃에 띄울 것인지, 어떤 프래그먼트인지 지정</li>
<li>setReorderingAllowed : 애니메이션 전환이 올바르게 작동하도록 트랜잭션과 관련된 fragment의 상태 변경을 최적화</li>
<li>addToBackStack :  뒤로가기 버튼 클릭 시 다음 액션</li>
</ul>
</li>
</ul>
<p>Fragment의 데이터전달</p>
<ol>
<li><p>Activity 에서 Fragment로 데이터 전달</p>
<ol>
<li>Fragment : newInstance()메서드로 받을 데이터 정의하기</li>
<li>Activity : newInstance() 호출해서 전달할 데이터 넣어주기</li>
<li>Fragment :  받은 데이터 사용하기</li>
</ol>
</li>
<li><p>Fragment 에서 Fragment로 데이터 전달</p>
<ol>
<li>받는 Fragment :  newInstance() 메서드에 받을 데이터 정의하기</li>
<li>보내는 Fragment : 데이터 보내는 event 시 받는 Fragment의 newInstance()호출해서 전달할 데이터 넣어주기</li>
</ol>
</li>
<li><p>Fragment 에서 Activity로 데이터 전달</p>
<p> 꼭 인터페이스를 정의해서 전달해야함. 그냥은 안됨</p>
<ol>
<li>Interface로 FragmentDataListenter를 정의</li>
<li>Activity :  정의한 인터페이스를 상속받아서 구현함 (데이터 받아서 할 행동 정의)</li>
<li>Fragment : 데이터 전달받을 Activity에서 인터페이스를 구현했는지 확인 후 리스너에서 인터페이스의 함수(데이터전달) 를 호출해서 전달할 데이터를 넣어줌</li>
</ol>
</li>
</ol>
<p>알아볼 것 :</p>
<p>Bundle 이무엇인가</p>
<p>requireActivity()는 무엇인가</p>
<h3 id="다이얼로그">다이얼로그</h3>
<p>사용자에게 결정을 내리거나, 추가정보를 입력하라는 메세지를 띄우는 작은 창</p>
<p>화면을 가득 채우지 않음</p>
<p>보통 사용자가 다음으로 진행하기 전에 조치를 취해야하는 모달 이벤트에서 사용</p>
<p><strong>Alert Dialog 다이얼로그 기본 구조</strong></p>
<ol>
<li>제목<ul>
<li>선택사항. 컨텐츠 영역에 상세한 메세지, 목록 또는 맞춤 레이아웃이 채워져 있는 경우에 사용</li>
<li>단순한 메세지, 질문을 나타내는 경우 제목은 없어도 ㄱㅊ</li>
</ul>
</li>
<li>컨텐츠 영역<ul>
<li>메세지, 목록 또는 다른 맞춤 레이아웃을 표시</li>
</ul>
</li>
<li>작업 버튼<ul>
<li>대화 상자 하나에 작업 버튼이 세개를 초과하면 안됨</li>
</ul>
</li>
</ol>
<h3 id="알림">알림</h3>
<p>앱의UI와 별도로 사용자에게 앱과 관련한 정보를 보여주는 기능</p>
<p>알림을 터치하면 해당 앱을 열 수 있음</p>
<h2 id="플로팅-버튼-이용해서-스크롤-조절">플로팅 버튼 이용해서 스크롤 조절</h2>
<p><strong>구현해야할 기능들</strong></p>
<ul>
<li><input checked="" disabled="" type="checkbox"> 스크롤을 최상단으로 이동시키는 플로팅 버튼 기능 추가</li>
<li><input checked="" disabled="" type="checkbox"> 플로팅 버튼은 스크롤을 아래로 내릴 때 나타나며, 스크롤이 최상단일때 사라집니다.</li>
<li><input checked="" disabled="" type="checkbox"> 플로팅 버튼을 누르면 스크롤을 최상단으로 이동시킵니다.</li>
<li><input checked="" disabled="" type="checkbox"> 플로팅 버튼은 나타나고 사라질때 fade 효과가 있습니다.</li>
<li><input checked="" disabled="" type="checkbox"> 플로팅 버튼을 클릭하면(pressed) 아이콘 색이 변경됩니다.</li>
</ul>
<h3 id="플로팅-버튼-디자인">플로팅 버튼 디자인</h3>
<ol>
<li><p>예제랑 최대한 비슷하게 만들기 위해서 일단 일러스트로 아이콘 하나 그려줌</p>
</li>
<li><p>xml에 플로팅액션버튼을 추가해주고 디자인을 비슷하게 만들어줌</p>
<ul>
<li><p><strong>기본 모양 바꾸기</strong></p>
<p>  내가 적용한 테마에서는 버튼이 기본 모양이 원형이아니고 모서리 둥근 네모 처럼 생김</p>
<ol>
<li><p>drawable에 shape_floatbtn 이라는 파일 하나 만들어서 원 모양 xml을 하나 만들어줌</p>
<pre><code class="language-kotlin">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;shape xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; android:shape=&quot;oval&quot;&gt;
 &lt;solid android:color=&quot;@color/white&quot;/&gt;
&lt;/shape&gt;</code></pre>
</li>
<li><p>floatingButton의 background와 shapeAppearance에 1번에서 만든 xml파일을 적용해줌</p>
<p>둘 중 하나 속성을 없애면 바로 네모가 되어버림 ;; 테마에 기본 적용된 모양이 네모라서 그런 것 같은데 테마에서 스타일을 변경해주는게 더 좋은 방법일 수도 있을듯</p>
<pre><code class="language-kotlin">android:background=&quot;@drawable/shape_floatbtn&quot;
app:shapeAppearance=&quot;@drawable/shape_floatbtn&quot;</code></pre>
</li>
</ol>
</li>
</ul>
</li>
</ol>
<pre><code>- **클릭시 색상 변경해주기**
    1. res 폴더에 color 폴더 하나 만들어주고 selector로 android : state_pressed 에 true/false 값 줘서 만들어줌!

    ```kotlin
    &lt;selector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
        &lt;item android:color=&quot;@color/white&quot; android:state_pressed=&quot;false&quot;/&gt; // 버튼 안누른 상태 일때 색 지정
        &lt;item android:color=&quot;#D3D3D3&quot; android:state_pressed=&quot;true&quot;/&gt; //버튼 누른 상태 일 때 색 지정
    &lt;/selector&gt;
    ```

    1. backgroundTint 속성에 정의해준 xml파일 넣어주기

    ```kotlin
    android:backgroundTint=&quot;@color/selector_floating_btn_color&quot;
    ```


- **기본적으로 들어가는 클릭시 색상 애니메이션? 제거**

    기본적으로 버튼을 누르면 연한 보라색으로 색상 애니메이션이 나오는데 개 열받음 찾아보니 ripple color 라고 함.

    rippleColor를 투명으로 바꿔줌

    ```kotlin
    app:rippleColor=&quot;@android:color/transparent&quot;
    ```</code></pre><h3 id="플로팅-버튼-기능">플로팅 버튼 기능</h3>
<ul>
<li><p><strong>리사이클러 뷰의 스크롤을 내렸을 때 플로팅 버튼이 나오고, 제일 상단에 있을 때는 사라지게 하는데 fadeIn, fadeout 으로 만들기</strong></p>
<ol>
<li><p>일단 사용하기 쉽게 플로팅 버튼을 변수에 담아주고, </p>
<p> fadeIn과 fadeOut효과는  AlphaAnimation을 사용해서 정의해 줌 (float 형식의 숫자를 넣어주면되고, 첫번째 인자로 시작시의 투명도 두번째 인자로 끝날때의 투명도) </p>
<pre><code class="language-kotlin"> val floatingBtn = binding.floatingBtn
 val fadeIn = AlphaAnimation(0f, 1f).apply { duration = 300 }
 val fadeOut = AlphaAnimation(1f, 0f).apply { duration = 300 }
 var isTop = true</code></pre>
</li>
<li><p>recyclerView에 addOnScrollListener를 달아줌</p>
<pre><code class="language-kotlin"> binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener(){
         override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
             super.onScrollStateChanged(recyclerView, newState)
         if (!binding.recyclerView.canScrollVertically(-1)&amp;&amp; newState == RecyclerView.SCROLL_STATE_IDLE) {
             binding.floatingBtn.startAnimation(fadeOut)
             binding.floatingBtn.visibility = View.GONE
             isTop = true
         }else if(isTop){
             floatingBtn.visibility = View.VISIBLE
             floatingBtn.startAnimation(fadeIn)
             isTop = false
         }
    }
 })</code></pre>
<p> ScrollListener로 스크롤이 변경되는 걸 감지?하게 만들어주고,</p>
<p> recyclerView가 -1방향 즉 위로 스크롤이 안되고, 현재 상태가 정지한 상태이면, </p>
<p> 플로팅 버튼이 서서히 사라지게 만들어줌.</p>
<p> 그렇지 않을 때에는 플로팅 버튼이 서서히 나타나게 만들어줌!</p>
</li>
</ol>
</li>
<li><p>플로팅 버튼을 클릭하면 스크롤을 맨 위로 이동 시킴</p>
<pre><code class="language-kotlin">  floatingBtn.setOnClickListener {
          binding.recyclerView.smoothScrollToPosition(0)
  }</code></pre>
<p>  플로팅 버튼을 클릭했을 때 smoothScrollToPosition 값을 0으로 줘서 최 상단으로 이동하게 해줌!</p>
<ul>
<li><p>리사이클러뷰의 스크롤 위치를 변경하는 다양한 메서드들</p>
<ul>
<li><p>scrollToPosition</p>
<p>  주어진 위치로 즉시 스크롤 ( 애니메이션 x)</p>
<pre><code class="language-kotlin">  recyclerView.scrollToPosition(position)</code></pre>
</li>
<li><p>scrollBy</p>
<p>  지정된 픽셀 수 만큼 스크롤 (수직 수평 스크롤 모두 가능)</p>
<pre><code class="language-kotlin">  recyclerView.scrollBy(x,y)</code></pre>
</li>
<li><p>smoothScrollBy</p>
<p>  지정된 픽셀 수 만큼 부드럽게 스크롤(수직 수평 스크롤 모두 가능)</p>
<pre><code class="language-kotlin">  recyclerView.smoothScollBy(dx,dy)</code></pre>
</li>
<li><p>LinearLayoutManager.scrollToPositionWithOffset</p>
<p>  특정 위치에 오프셋을 적용하여 스크롤 (특정 항목을 리스트의 상단 혹은 중단에 배치)</p>
<pre><code class="language-kotlin">  val layoutManager = recyclerView.layoutManager as LinearLayoutManager
  layoutManager.scrollToPositionWithOffset(position,offset)</code></pre>
</li>
<li><p>layoutManager.startSmoothScroll</p>
<p>  사용자 정의 스크롤 동작을 구현, 세밀한 제어 가능</p>
<pre><code class="language-kotlin">  val layoutManager = recyclerView.layoutManager as LinearLayoutManager
  val scroller = object : LinearSmoothScroller(recyclerView.context) {
          override fun getVerticalSnapPreference() : Int {
                  return SNAP_TO_START
          }
  }
  scroller.targetPosition = position
  layoutManager.startSmoothScroll(scroller)</code></pre>
</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[첫 프로젝트 정리] TIL 0708 ]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%B2%AB-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A0%95%EB%A6%AC-TIL-0708</link>
            <guid>https://velog.io/@orinugoori_art/%EC%B2%AB-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A0%95%EB%A6%AC-TIL-0708</guid>
            <pubDate>Mon, 08 Jul 2024 12:24:41 GMT</pubDate>
            <description><![CDATA[<p>일주일간 미뤄둔 TIL 드디어 다시 컴백!</p>
<p>지난 일주일은 첫 프로젝트 주간이라 진짜 정신이 하나도 없었다.</p>
<p>프로젝트를 잘 완수하고싶어서 코드카타도 미뤄두고 프로젝트에만 매진했는데도</p>
<p>금요일까지 끝내려고 했던 계획이 무산되고 주말까지 나와서 다들 고생하셨당..</p>
<p>우리팀 체고!!!</p>
<p>기록도 열심히 했어야했는데 기록도 제대로 못하고 진행해서 </p>
<p>다 끝낸 오늘 기억나는 것들 위주로 첫번째 프로젝트를 정리할 것!</p>
<h1 id="프로젝트-개발일지">프로젝트 개발일지</h1>
<p>팀 이름 : 주빈과 아이들</p>
<p>프로젝트 주제 : SNS 앱 만들기</p>
<p><strong>프로젝트 필수 구현사항</strong></p>
<ul>
<li><input disabled="" type="checkbox"> 메인 화면</li>
<li><input disabled="" type="checkbox"> 디테일 화면</li>
<li><input disabled="" type="checkbox"> 로그인 회원가입 화면</li>
<li><input disabled="" type="checkbox"> 마이 페이지 화면</li>
<li><input disabled="" type="checkbox"> Activity 전환 시 애니메이션 구현</li>
<li><input disabled="" type="checkbox"> 영어버전 적용하기</li>
</ul>
<p><strong>프로젝트 선택 구현사항</strong></p>
<ul>
<li><input disabled="" type="checkbox"> ImageView 동그랗게 만들기</li>
<li><input disabled="" type="checkbox"> 스크롤기능 사용하기</li>
<li><input disabled="" type="checkbox"> 더보기 기능</li>
<li><input disabled="" type="checkbox"> Font 크기 설정에 따라 글씨 크기 달라지게 만들기</li>
<li><input disabled="" type="checkbox"> Dark Theme 구현하기</li>
<li><input disabled="" type="checkbox"> 가로모드 구현하기</li>
<li><input disabled="" type="checkbox"> 회원정보 관리 구현하기</li>
</ul>
<h1 id="개발-타임라인">개발 타임라인</h1>
<h1 id="1-첫-기획-회의">1. 첫 기획 회의</h1>
<p><strong>1.회의 방식</strong></p>
<p>Figma 잼에서 아이디어 회의 , Figma로 와이어 프레임 제작</p>
<p><strong>2.논의한 내용</strong></p>
<ul>
<li>앱의 주제 ( sns의 메인 주제 정하기)</li>
<li>앱 이름, 아이콘 컨셉 투표</li>
<li>앱 컬러코드와, 폰트사이즈 등 논의</li>
<li>개발 룰( IDE, SDK, 등 등 개발환경, Git Commit 규칙, 브랜치 규칙 등)</li>
<li>각 화면 구성요소, 디자인 논의</li>
<li>인원 배분</li>
</ul>
<p><strong>3.논의 결과</strong> </p>
<ul>
<li><p>앱 이름 : PlayList</p>
</li>
<li><p>앱 주제 : 종합 게임의 리뷰를 공유하며 본인 취향에 맞는 게임을 찾을 수 있게 도와주는 SNS</p>
</li>
<li><p>컬러 코드</p>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/5fa1bf7c-63ab-4fb7-98af-170a8ff33006/image.png" alt=""></p>
<p>  Primary Color :  A2C9E9</p>
<p>  Secondary Color : D4E2ED</p>
<p>  White : FFFFFF</p>
<p>  Gray : BCBCBC</p>
<p>  Black : 222222</p>
</li>
<li><p>폰트  &amp; 사이즈</p>
<p>  폰트 : Pretendard</p>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/4a7216df-e5ad-46bf-9a19-10206208d67f/image.png" alt=""></p>
</li>
</ul>
<ul>
<li><p>개발 룰 :</p>
<ul>
<li><p>Android Studio 버전 : jellyfish</p>
</li>
<li><p>SDK 14.0</p>
</li>
<li><p>Emulator Pixel 7 API 33</p>
</li>
<li><p>깃 컨벤션 :</p>
<p>   작업한사람인식코드(맡은 Activity 첫글자)_ 날짜.주(완성).부(기능).패치(소소한추가, 수정)</p>
<p>  아이디이름 규칙 : 뷰종류_사용액티비티_기능</p>
</li>
</ul>
</li>
</ul>
<ul>
<li>와이어프레임? 디자인?</li>
</ul>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/f83ebf7b-46ed-4975-9026-8a5d7e62eb80/image.png" alt=""></p>
<p>피그마로 회의하면서 와이어 프레임이 뭔지 모르는 분도 계시고 해서</p>
<p>와이어 프레임 설명드리고, 어떻게 디자인 회의를 할까 하는데, 사실 나는 한명이 디자인 싹 맡아서 하는게 효율은 제일 나을 것 같았지만, 그러면 모두의 의견을 다 반영하기 어려울 것 같고, 다들 피그마 사용에 익숙해지면 좋은데 피그마를 한번도 안 써보신 분도 게셔서 그냥 다들 페이지 하나씩 맡아서 진행하면 경험이 되어서 발전하는데에는 더 좋지 않을까해서 각자 페이지 하나씩을 디자인 맡았다.</p>
<p>근데 처음에는 와이어 프레임 건너뛰고 바로 디자인 할 것 처럼 말했던 것 같은데 만들고 보니 나만 디자인처럼 만들고 다른 분들은 와이어 프레임으로 만들어놓으셔서 좀 통일이 안됐다..ㅜ</p>
<p>나중에 끝나고는 다들 그냥 한명이 맡아서 하는게 나았을 것 같다고 하는 의견이 나와서 앗..그냥 그때 얘기할 걸 싶은 생각이 들었지만 그래도 나는 다 같이 참여해서 피그마 한번씩 만져보고, UI 구성에 의견 내보고 하는게 나쁘지 않았다고 생각함~!</p>
<ul>
<li><p>인원 배분</p>
<p>  대충 만들어 놓은 디자인인지 와이어프레임인지 모를 놈들을 가지고 인원 배분을 했다.</p>
<p>  나는 어떤 액티비티를 해도 상관이 없어서 다른 분들에게 선택권을 드리고 남은걸 가져옴!</p>
<p>  나는 Detail Activity를 맡게 되었당!</p>
<p>  사람은 다섯인데 페이지는 여섯개라서 가장 UI적으로 간단한 회원가입 로그인을 한 사람이 맡기로 했다! </p>
</li>
</ul>
<h1 id="2-git-repository-생성-후-브랜치-나누고-개발시작">2. Git Repository 생성 후 브랜치 나누고 개발시작</h1>
<p>개별적으로 작업을 들어가기 전, 레포지토리를 생성하고, 기초 프로젝트를 만들고, dev브랜치를 만들고 각자 feature 브랜치를 만들어서 작업을 시작했다.</p>
<p>나는 Detail Activity 를 맡아서 작업했기 때문에 </p>
<p>feature_detail이라는 브랜치를 만들어서 작업했다.</p>
<p>처음 협업 때 뭔지도 모르고 git 써봤던게 그래도 많이 도움이 됐다.</p>
<p>역시 서당개 삼년이면 풍월을 읊는다는 말이 쌩구라가 아님. 옆에서 뭔지도 모르는걸 보기만 해도 나중에 직접 할 때 훨씬 도움이 된다.</p>
<p>사실 내가 맡은 페이지가 그렇게 어려운 페이지가 아니여서 처음에는 딱히 어려운 점이 없었다.</p>
<h2 id="datail-activity-에서-사용한-기술-중-기억에-남는-것들">Datail Activity 에서 사용한 기술 중 기억에 남는 것들</h2>
<h2 id="1-rating-bar"><strong>1. Rating Bar</strong></h2>
<p>구성하던 중에 별점 주는 기능은 어떻게 구현할까. 하고 찾다가 Rating Bar라는 걸 알았다.</p>
<p>ㄹㅇ 개꿀 기능! </p>
<p>이런게 있는지 모르고 처음에 별점 구상했을때는 </p>
<p>코드로 직접 짜야되는 줄만 알고 고생할수도 있겠다 생각했는데 Rating Bar라는 기능이 있어서 쉽게구현했다.</p>
<p>Rating Bar 간단 설명</p>
<ul>
<li><p>간단하게 별점을 구현할 수 있는 기능</p>
</li>
<li><p>유용한 속성</p>
<ul>
<li>isIndicator : false로 두면 화면에서 유저가 직접 별점을 드래그해서 움직일 수 있어지고, true로 두면 초기에 지정된 별점이 그대로 유지된다.</li>
<li>numStars : Int값대로 별의 최대 개수가 설정된다.</li>
<li>rating : 초기에 설정하는 값</li>
<li>stepSize : 별점의 점수가 움직이는 최소단위를 설정할 수 있다.</li>
</ul>
</li>
<li><p>내가 사용한 예시</p>
<pre><code class="language-kotlin">  &lt;RatingBar
          android:id=&quot;@+id/rb_d_user_rating&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:layout_height=&quot;wrap_content&quot;
          android:layout_marginTop=&quot;16dp&quot;
          android:isIndicator=&quot;true&quot;
          android:numStars=&quot;5&quot;
          android:progressTint=&quot;@color/primary&quot;
          android:rating=&quot;3.5&quot;
          android:stepSize=&quot;0.5&quot;
          app:layout_constraintStart_toStartOf=&quot;@id/tv_d_username_rating&quot;
          app:layout_constraintTop_toBottomOf=&quot;@id/tv_d_subtitle_user_rating&quot; /&gt;</code></pre>
</li>
</ul>
<h2 id="2-include"><strong>2. include</strong></h2>
<p>처음에는 바텀 네비게이션 바를 만들어서 서로 넣어주기 위해서 사용했는데, 결국 나중에는 모션레이아웃을 사용하게 되면서 코드가 복잡해져서 하나의 xml에서 작성했던 애들을 header와 scroll 파트로 나눠서 각각 다른 xml에 옮겨적어주고, include로 가져왔다.</p>
<p>include 간단 설명</p>
<ul>
<li><p>다른 xml 파일을 간단하게 해당 xml에 가져와서 xml 파일의 재사용성을 높여주는 기능</p>
</li>
<li><p>사용방법 : 간단하게 그냥 include 태그를 열어주고 layout=”가져올 레이아웃 이름” 적어주면 끝</p>
</li>
<li><p>내가 사용한 예시</p>
<pre><code class="language-kotlin">  &lt;include
      android:id=&quot;@+id/d_navigation&quot;
      layout=&quot;@layout/bottom_navigation_view&quot;
      android:layout_width=&quot;match_parent&quot;
      android:layout_height=&quot;wrap_content&quot;
      app:layout_constraintBottom_toBottomOf=&quot;parent&quot;/&gt;</code></pre>
</li>
</ul>
<h2 id="3-regex-이용한-가격-표시"><strong>3. Regex 이용한 가격 표시</strong></h2>
<p>게임의 가격 정보를 받아서 표시할 때 받는 정보에서는 그냥 Int값이 들어오는데, 그러면 너무 보기 어렵기도 하고 딱 보기에 예쁘지가 않길래, Regex를 통해서 받은 값에 콤마를 찍어서 표시하도록 만들어줬다. </p>
<p>tmi : 처음 써보는 건 아니지만, 프로젝트나 과제에서 실사용? 하는 건 처음이라서 미리 공부해놓은게 뿌듯해짐!</p>
<p>Regex 간단 설명</p>
<ul>
<li><p>Regular Express 의 줄임말. 정규식이라고도 부른다.</p>
</li>
<li><p>어떤 문자열의 패턴을 분석하여 변환해주거나, 유효성 검사를 하거나 등에 자주 쓰임</p>
</li>
<li><p>내가 사용한 예시</p>
<pre><code class="language-kotlin">  fun priceRegex(priceString: String): String {
          var finalPrice = &quot;&quot;
          if (priceString == &quot;0&quot;) {
              finalPrice = &quot;무료 게임&quot;
          } else {
              val regex = Regex(&quot;(\\d)(?=(\\d{3})+(?!\\d))&quot;)
              finalPrice = &quot;₩ &quot; + priceString.replace(regex, &quot;$1,&quot;)
          }
          return finalPrice
      }</code></pre>
</li>
</ul>
<h2 id="4-텍스트-더보기-기능">4. 텍스트 더보기 기능</h2>
<p>리뷰의 글 부분이 길 때 처음부터 리뷰를 전부 표시하지 않고, 처음에는 두줄만 보이다가 유저가 더보기를 클릭하면 리뷰를 전부 볼 수 있게 만들었다.</p>
<p>TextView의 maxlines와 ellipsize라는 속성을 조정해서 만듦</p>
<p>maxlines : 텍스트뷰가 보이는 최대 줄 수 설정</p>
<p>ellipsize : 속성을 end로 주면 maxline으로 줄여졌을 때 보이는 마지막 글자들 뒤에 …이 붙어서 나온다.</p>
<ul>
<li>내가 사용한 예시</li>
</ul>
<pre><code class="language-kotlin">userReview.maxLines = Int.MAX_VALUE

        userReview.viewTreeObserver.addOnGlobalLayoutListener(object :
            ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                if (userReview.lineCount &lt;= 2) {
                    showMore.visibility = View.GONE
                } else {
                    showMore.visibility = View.VISIBLE
                }

                userReview.maxLines = 2
                userReview.viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
        showMore.setOnClickListener {
            if (userReview.maxLines == 2) {
                userReview.maxLines = Int.MAX_VALUE
                showMore.text = &quot;닫기&quot;
            } else {
                userReview.maxLines = 2
                showMore.text = &quot;더보기&quot;
            }
        }</code></pre>
<p>추가 설명 : 처음에는 showMore.setOnClickListener로만 만들었는데 저렇게만 하니까</p>
<p>애초에 2줄이 안넘는 짧은 리뷰에도 더보기가 있어서 UX적으로 사용자가 헷갈릴 것 같아서 애초에 2줄이 안되는 리뷰에는 더보기가 나오지 않게 만들어주기 위해서 viewTreeObserver를 사용해서 뷰가 그려진 이후에 라인을 세고 줄 수에 따라서 더보기의 visibility를 설정해주었다.</p>
<h2 id="5overridependingtransition">5.overridePendingTransition</h2>
<p>필수 구현사항인 액티비티 전환 시 애니메이션 구현을 하기위해 넣었다.</p>
<p>나는  화면 디자인에 어울리게 메인 액티비티에서 디테일 화면을 눌렀을 때 아래에서 위로 화면이 나오는 것처럼 나오고, 닫기를 누르면 아래로 다시 내려가면서 종료되게 만들었다.</p>
<p>overridePendingTransition 간단 설명</p>
<ul>
<li><p>이제는 deprecated 된 코드임</p>
<p>  (하지만 먼저 애니메이션 적용하신 팀원 분이 이걸로 적용하셔서 통일성을 위해? 그리고 따로 새로운 방법을 공부할 시간이 별로 없었어서 해당 기능을 사용했다.)</p>
</li>
<li><p>사용방법 :</p>
<ol>
<li>xml 로 <set>태그를 사용해서 translate를 지정해줌 ( 액티비티의 이동을 어떻게 할건지와 애니메이션 지속시간을 정의)</li>
<li>코드에서 적용</li>
</ol>
</li>
<li><p>내가 사용한 예시</p>
<pre><code class="language-kotlin">          overridePendingTransition(R.drawable.slideup, R.drawable.no_animation)

          val back = findViewById&lt;ImageView&gt;(R.id.iv_icon_back) // &lt; 뒤로가기 버튼

          back.setOnClickListener {
              super.finish()
              overridePendingTransition(0,R.drawable.slideout)
          }</code></pre>
<pre><code class="language-kotlin">  &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
      &lt;translate
          android:fromYDelta=&quot;100%&quot;
          android:toYDelta=&quot;0%&quot;
          android:duration=&quot;500&quot;/&gt; &lt;!-- 애니메이션 지속 시간 (밀리초) --&gt;
  &lt;/set&gt;</code></pre>
</li>
<li><p>주의 사항 : drawable의 아이디 값을 인자로 받기 때문에 0으로 주면 애니메이션이 적용안되는 것과 같지만, 0으로 주는것과 <set>파일을 만들고 거기에 아무것도 적지 않은 파일을 만들어서 적용해주는 것과 차이가 있을 수 있음</p>
</li>
<li><p>아직 정확히 왜인지는 모르지만 뒤로가기 버튼에서 첫번째 인자를 0으로 주었을때는 뒤의 메인 액티비티가 잘 보이는 상태로 내 액티비티가 내려가는데, 내 애니메이션이 등장할때에는 빠지는 액티비티의 애니메이션을 0으로 주면 애니메이션이 시작되면서 뒤에 화면이 메인액티비티가안나오고 검은색이 표시됨.</p>
</li>
</ul>
<h2 id="6-motion-layout">6. Motion Layout</h2>
<p>튜터님이 Sa 피드백으로 이런 레이아웃이면 모션 레이아웃을 사용해서 해보면 좋을 것 같다고 한번 공부해서 넣어보라고 미션같은 아이디어를 주시고,, 참고할 자료도 주셔서 공부해서 적용함!</p>
<p>모션 레이아웃 간단 설명</p>
<ul>
<li>레이아웃에 모션을 줄 수 있게 컨스트레인트 레이아웃의 업그레이드 버전</li>
<li>scene.xml 파일을 작성해주고 layout description에 넣어주면 된다.</li>
<li>scene 파일에는 start와 end의 아이디와, 각 모션 적용해줄 애들의 위치를 지정해주면 됨</li>
<li>scene 파일에서는 OnSwipe , OnClick 으로 트리거 옵션도 설정 할 수 있다.</li>
<li>scene파일에서는 레이아웃에 대한 위치 조절만 가능하고, 뷰의 옵션을 조절하고 싶을 때는 코틀린 코드에서.setTransitionListener를 사용해서 시작시점의 속성,  변화 중의 속성, 전환완료시의 속성, 트리거시의 속성 등을 설정할 수 있다.</li>
</ul>
<h3 id="그-외-작업하면서-알게된-소소한-팁">그 외 작업하면서 알게된 소소한 팁..?</h3>
<p>println으로 로그 확인하는 방법</p>
<p>drawable id? 나 id 값들이 인트값이였다는것?</p>
<p>log로 찍어보면서 오류 해결하는 방식</p>
<h2 id="3-1차-개발-완료-후-머지">3. 1차 개발 완료 후 머지</h2>
<p>한번 다같이 dev에 머지를 하고  작업 진행 상황을 한번 확인하고, 어떤걸 더 하면 좋을지 등을 논의 했다.</p>
<p>건의사항 : </p>
<ul>
<li>로고에서 글씨부분에서 list크기를 줄이고 play색을 더강조하는 방식으로 좀 수정하는 거 어떨까용</li>
<li>앱 시작화면, 어플 아이콘 넣고싶슴당(시간모자라면 주말에 김현지가 추가 가능)</li>
</ul>
<p>로그인 : </p>
<ul>
<li>회원가입 로그인 기능 구현,</li>
<li>싱글톤으로 데이터 받는거</li>
</ul>
<p>메인 : </p>
<ul>
<li>네비바로 다른 페이지 인텐트</li>
<li>뷰페이저2 인디케이터 제작</li>
<li>인게임 스크린샷 전부 가져오기</li>
</ul>
<p>디테일 : </p>
<ul>
<li>인게임 스크린샷 데이터 추가 (갓화민님)</li>
<li>해시태그 정렬정리</li>
<li>가격 표시 regex추가 (유료게임은 ,랑 원화 표시나 달러표시/ 무료게임은 0말고 무료 라고 표시)</li>
<li>리뷰 line 2줄이하면 더보기 visiblility 변경</li>
<li>모션레이아웃 올렸을때 해시태그 maxline 변경</li>
</ul>
<p>탐색 : </p>
<ul>
<li>네비바 인텐트</li>
<li>네비바 기본선택 아이템 탐색으로변경</li>
<li>각 사진에 clipToOutline사용해서 모서리 둥글게 적용</li>
<li>고객님을 위한 추천 스크롤뷰 , 네비바 ? 사이 마진 더 늘리기</li>
</ul>
<p>프로필 : </p>
<ul>
<li>네비바 인텐트</li>
<li>네비바 기본선택 아이템 프로필로 변경</li>
<li>게임장르별 이미지</li>
<li>프로필 이미지 clipToOutline 적용 (건의사항)</li>
<li>이름 자기소개 textColor white로하고 뒤 이미지를 어둡게 하는거?(건의사항)</li>
</ul>
<h2 id="4-각자-버그수정사항-픽스">4. 각자 버그/수정사항 픽스</h2>
<p>다른 분들 화면을 다 받아와서 보면서 피드백을 진행하고, 각자 다시 수정함!</p>
<p>이 쯤 부터 슬슬 완성 된 사람은 아직 안 된 사람이나 어려움이 있는 사람가서 도와주기도하고 </p>
<p>주말에 시간 얼마 안 남았을 때는 그냥 아예 기능 몇개 맡아서 추가해주거나 했음!</p>
<h2 id="5-작업-완료-후-dev에서-버그--추가-수정사항-찾기">5. 작업 완료 후 dev에서 버그 , 추가 수정사항 찾기</h2>
<p>작업 완료 후에 이제 dev에 전부 머지하고 각자 에뮬레이터로 테스트해보면서 버그나 수정사항을 찾아서 수정했다.</p>
<h2 id="6-완료-후-제출">6. 완료 후 제출!</h2>
<p>다 끝나고 dev에서 main으로 머지하고 제출!!!</p>
<p>우리는 결국 다크모드, 폰트크기 설정에따라 변경, 가로모드 구현은 못하고 나머지는 다 했다!!</p>
<h1 id="첫-프로젝트-후기">첫 프로젝트 후기</h1>
<p>다행히 첫 프로젝트를 하는 팀이 너무 잘걸려서 다들 본인 의견 피력을 잘하시고,</p>
<p>각자 맡은일도 열심히 해주시고, 시간약속도 잘지켜주시고, 주말까지 나와서 작업하실만큼 열의가 있는 분들이 계셨다.</p>
<p>제각각의 실력인 사람들이 한 팀으로 묶어서 처음으로 작업해보는 거다 보니까 답답해 한다거나, 게을러진다거나, 주눅이 든다거나 할 수있는데 팀원들 모두 그런거없이 적극적으로 참여해주시고 모르는 부분도 잘 질문하면서 해결해나가셔서 무사히 마무리 할 수 있었다고 생각한다.</p>
<p>나는 사실 주말에도 원래 나와서 혼자 공부하는 사람이라 괜찮았는데 다른 분들은 주말에 나와야할 때 싫어하실까봐 걱정을 했는데 다들 나와서 너무 열심히 해주심.</p>
<p>나도 회원가입 기능 맡은 분이 로그인 페이지랑 두개 다 맡으면서 너무 버거우신 것같아서 그분 퇴근후에 따로 남아서 회원가입 기능이나 UI수정을 했는데, 우리팀 코딩 챌린저분도 같이 새벽 5시 까지 남아서 같이 해주셨다.. 본인 파트만 하셨으면 이미 끝내셨을 걸 다른 분들 먼저 도와주시느라 자기파트도 미루고 늦게까지 남아서 해주시는게 아주아주 감동이였다..두번째 같은팀이였는데.. 또같은팀되고싶다…사실 조바뀌는게 너무 싫다!!!이번 조 좋았는데!!!!!!!!분위기 짱이였는데!!!!!!!!!!!!!!!!!!!!</p>
<p>아쉬운건 매니저님들이 ppt만드는데 너무 시간쓰지말고 발표준비보단 개발에 집중하라고 하도 강조하시길래 발표준비 너무 열심히 만들면 혼날까봐 신경안썼는데,,, 다른 조들 보니까 너무 ppt를 예쁘게 만 들어오셔서 우리도 피피티 열심히 만들어올걸!하고 아쉬웠다 나는 평소에 ppt가 굉장히 중요하다고 생각해서 원래같으면 최대한 열심히 만들었을텐데 일부러 대충만든건데…………..우리 팀 열심히 만든 앱이 생각보다 어필이 안된 것같아서 조금 속상했다….</p>
<p>그래도 주말까지 나와서 최선을 다해서 진행했기도 하고, 소통이 원활하게 되었어서 아주 행복했당!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 53 (명예의 전당 1)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-53-%EB%AA%85%EC%98%88%EC%9D%98-%EC%A0%84%EB%8B%B9-1</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-53-%EB%AA%85%EC%98%88%EC%9D%98-%EC%A0%84%EB%8B%B9-1</guid>
            <pubDate>Tue, 02 Jul 2024 00:52:52 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>&quot;명예의 전당&quot;이라는 TV 프로그램에서는 매일 1명의 가수가 노래를 부르고, 시청자들의 문자 투표수로 가수에게 점수를 부여합니다. 매일 출연한 가수의 점수가 지금까지 출연 가수들의 점수 중 상위 k번째 이내이면 해당 가수의 점수를 명예의 전당이라는 목록에 올려 기념합니다. 즉 프로그램 시작 이후 초기에 k일까지는 모든 출연 가수의 점수가 명예의 전당에 오르게 됩니다. k일 다음부터는 출연 가수의 점수가 기존의 명예의 전당 목록의 k번째 순위의 가수 점수보다 더 높으면, 출연 가수의 점수가 명예의 전당에 오르게 되고 기존의 k번째 순위의 점수는 명예의 전당에서 내려오게 됩니다.</p>
<p>이 프로그램에서는 매일 &quot;명예의 전당&quot;의 최하위 점수를 발표합니다. 예를 들어, <code>k</code> = 3이고, 7일 동안 진행된 가수의 점수가 [10, 100, 20, 150, 1, 100, 200]이라면, 명예의 전당에서 발표된 점수는 아래의 그림과 같이 [10, 10, 10, 20, 20, 100, 100]입니다.</p>
<p>명예의 전당 목록의 점수의 개수 <code>k</code>, 1일부터 마지막 날까지 출연한 가수들의 점수인 <code>score</code>가 주어졌을 때, 매일 발표된 명예의 전당의 최하위 점수를 return하는 solution 함수를 완성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>3 ≤ <code>k</code> ≤ 100</li>
<li>7 ≤ <code>score</code>의 길이 ≤ 1,000<ul>
<li>0 ≤ <code>score[i]</code> ≤ 2,000</li>
</ul>
</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(k: Int, score: IntArray): MutableList&lt;Int&gt; {
        var faker = mutableListOf&lt;Int&gt;()
        var answer = mutableListOf&lt;Int&gt;()

        for(i in 0..score.size-1){
            if(i&lt;k){
                faker.add(score[i])
                faker.sort()
            }else{
                if (score[i] &gt; faker[0]){
                    faker.add(score[i])
                    faker.sort()
                    faker.removeAt(0)
                    println(faker)
                }
            }
            answer.add(faker[0])
        }

        return answer
    }
}</code></pre>
<p>명예의전당 변수 이름이 너무 어려워서 대상혁으로 지어버림</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[내배캠 Android 4기] TIL 0701]]></title>
            <link>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0701-jub6gaki</link>
            <guid>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0701-jub6gaki</guid>
            <pubDate>Mon, 01 Jul 2024 11:52:18 GMT</pubDate>
            <description><![CDATA[<p>오늘 할일</p>
<ul>
<li><input checked="" disabled="" type="checkbox"> 코드카타 52번</li>
<li><input disabled="" type="checkbox"> 개인과제 해설 확인</li>
<li><input checked="" disabled="" type="checkbox"> 피그마 강의</li>
<li><input disabled="" type="checkbox"> git 협업 특강</li>
</ul>
<hr>
<h2 id="코드카타">코드카타</h2>
<p>오늘은 문제가 길긴한데.. 사실상 어려울게 하나도 없는 문제였당</p>
<p>근데 수학적으로 생각해서 코드를 짜야하는데</p>
<p>수학적 사고에 약하기 때문에 암산으로 생각이 불가능해서</p>
<p>노트에 적으면서 함~ 근데 막상 적으면 ㅈㄴ간단한거라 헛웃음나옴 ㅜ</p>
<p>왜 이것도 암산으로 못하는데..? ㅜㅜ</p>
<p>아무튼 .. 혼자서는 좀 부끄러웠지만 결과적으론 잘풀었으니 됐음</p>
<p><a href="https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-52-%EC%BD%9C%EB%9D%BC-%EB%AC%B8%EC%A0%9C-243hoqkl">https://velog.io/@orinugoori_art/알고리즘-CODEKATA-52-콜라-문제-243hoqkl</a></p>
<hr>
<h2 id="피그마-강의">피그마 강의</h2>
<p>팀프로젝트 시작전에</p>
<p>제공된 피그마 강의를 들었당</p>
<p>기본적인 단축키, 프레임 만드는방법, </p>
<p>텍스트스타일이나 컬러스타일 지정하는 것, 오토레이아웃 적용하는 방법 등에 대해서 알게되었당</p>
<p>근데사실 실질적으로 내기준으론 일러스트만큼 편하게 쓰려면 따로 공부할게 너무 많을 것같아서 어지러움.. 언제공부하지저건또…</p>
<hr>
<h2 id="git-특강">git 특강</h2>
<p>이것도 내일부터 팀프로젝트 시작이라</p>
<p>협업에 필요한 기본적인 기능들을 알려주시는 실시간 강의를 배치해주셔서 들었음</p>
<p>브랜치따는법이나 머지하는방법, 깃허브에서 pullrequest 하는방법 등을 배웠음!</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 52 (콜라 문제)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-52-%EC%BD%9C%EB%9D%BC-%EB%AC%B8%EC%A0%9C-243hoqkl</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-52-%EC%BD%9C%EB%9D%BC-%EB%AC%B8%EC%A0%9C-243hoqkl</guid>
            <pubDate>Mon, 01 Jul 2024 00:45:00 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>오래전 유행했던 콜라 문제가 있습니다. 콜라 문제의 지문은 다음과 같습니다.</p>
<blockquote>
<p>정답은 아무에게도 말하지 마세요.</p>
<p>콜라 빈 병 2개를 가져다주면 콜라 1병을 주는 마트가 있다. 빈 병 20개를 가져다주면 몇 병을 받을 수 있는가?</p>
<p>단, 보유 중인 빈 병이 2개 미만이면, 콜라를 받을 수 없다.</p>
</blockquote>
<p>문제를 풀던 상빈이는 콜라 문제의 완벽한 해답을 찾았습니다. 상빈이가 푼 방법은 아래 그림과 같습니다. 우선 콜라 빈 병 20병을 가져가서 10병을 받습니다. 받은 10병을 모두 마신 뒤, 가져가서 5병을 받습니다. 5병 중 4병을 모두 마신 뒤 가져가서 2병을 받고, 또 2병을 모두 마신 뒤 가져가서 1병을 받습니다. 받은 1병과 5병을 받았을 때 남은 1병을 모두 마신 뒤 가져가면 1병을 또 받을 수 있습니다. 이 경우 상빈이는 총 10 + 5 + 2 + 1 + 1 = 19병의 콜라를 받을 수 있습니다.</p>
<p>문제를 열심히 풀던 상빈이는 일반화된 콜라 문제를 생각했습니다. 이 문제는 빈 병 <code>a</code>개를 가져다주면 콜라 <code>b</code>병을 주는 마트가 있을 때, 빈 병 <code>n</code>개를 가져다주면 몇 병을 받을 수 있는지 계산하는 문제입니다. 기존 콜라 문제와 마찬가지로, 보유 중인 빈 병이 <code>a</code>개 미만이면, 추가적으로 빈 병을 받을 순 없습니다. 상빈이는 열심히 고심했지만, 일반화된 콜라 문제의 답을 찾을 수 없었습니다. 상빈이를 도와, 일반화된 콜라 문제를 해결하는 프로그램을 만들어 주세요.</p>
<p>콜라를 받기 위해 마트에 주어야 하는 병 수 <code>a</code>, 빈 병 a개를 가져다 주면 마트가 주는 콜라 병 수 <code>b</code>, 상빈이가 가지고 있는 빈 병의 개수 <code>n</code>이 매개변수로 주어집니다. 상빈이가 받을 수 있는 콜라의 병 수를 return 하도록 solution 함수를 작성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>1 ≤ <code>b</code> &lt; <code>a</code> ≤ <code>n</code> ≤ 1,000,000</li>
<li>정답은 항상 int 범위를 넘지 않게 주어집니다.</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<p><strong>최종코드</strong></p>
<pre><code class="language-kotlin">class Solution {
    fun solution(a: Int, b: Int, n: Int): Int {
        var answer: Int = 0
        var num = n

        while(num &gt;= a){
           val addCola = (num /a) *b
            answer += addCola
            num = addCola + (num%a)
        }

        return answer
    }
}</code></pre>
<p>푸는데 사실 안어려운문제같은데 </p>
<p>수학적으로 생각하려니까 머리가 안돌아가서 암산으로 풀다가</p>
<p>자꾸 헷갈려서 그냥 공책에 ㅋㅋㅋㅋ적으면서 함</p>
<hr>
<h3 id="다른-사람-풀이">다른 사람 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(a: Int, b: Int, n: Int): Int {
        return (if (n &gt; b) n - b else 0) / (a - b) * b
    }
}</code></pre>
<p>이거는 댓글로 수학적으로 이런 공식 어떻게 생각하냐는 감탄들이 잔뜩 달려있던 풀이</p>
<p>봐도 모르겠음 이게 왜 되는거임!?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[내배캠 Android 4기] TIL 0630]]></title>
            <link>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0630</link>
            <guid>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0630</guid>
            <pubDate>Sun, 30 Jun 2024 20:25:16 GMT</pubDate>
            <description><![CDATA[<h2 id="네비게이션-바-아이템-눌렀을때-intent로-화면-이동">네비게이션 바 아이템 눌렀을때 Intent로 화면 이동</h2>
<p>두번째 액티비티의 xml은 대충 작성이 끝났는데</p>
<p>외부 라이브러리를 사용해서 코틀린 파일에서 설정해주어야 하는 부분들이 남아서 </p>
<p>잘 적용되는지 보려면 화면 이동을 해줘야하기때문에 네비게이션바에서 이동할 수 있게 추가해줌!</p>
<p>사실 원래는 머.. 네비게이션 바로 이동할 때, 특히 지금 내 상황에서는 프래그먼트라던지 그런거 써야될 것 같지만 배운개념 내에서 구현하는게 좋으니까 그냥 무식하게 했당~</p>
<p>먼가 검색 없이 대충 할 수 있을 것같아서</p>
<p>네비게이션 바를 코틀린 파일에 연동해주고,</p>
<p>.눌러서 setOnClickListner같이 생긴 애를 찾아서 쭉내리니까 </p>
<p>setOnNavigationItemListener라는게 있길래</p>
<p>사용해주고, when문을 사용해서 각 페이지로 이동할 수 있게 해줬다.</p>
<pre><code class="language-kotlin">        navigateBar.setOnNavigationItemSelectedListener{item -&gt;
            when (item.itemId) {
                R.id.home -&gt; {
                    val intent = Intent(this,MainActivity::class.java)
                    startActivity(intent)
                    true
                }
                R.id.search -&gt; {
                    intent = Intent(this,SearchActivity::class.java)
                    startActivity(intent)
                    true
                }
                R.id.library -&gt; {
                    intent = Intent(this,LibraryActivity::class.java)
                    startActivity(intent)
                    true
                }
                else -&gt; false

            }
        }
</code></pre>
<p>처음에는 ItemId 랑 <a href="http://R.id">R.id</a> 안붙여주고, true도 안붙여줘서 안됐었음.</p>
<p>그래서 결국 검색 때려서 알아냈당~</p>
<p>뇌내망상으로 해결하고싶었는데 역시 쉽지않당~</p>
<p>LibraryActivity는 아직 구현은안했지만 빈액티비티 그냥 만들어서 넣어놨음</p>
<p>그리고 SearchActivity에도 네비게이션바를 추가해줬는데,</p>
<p>이게 Fragment를 쓰거나하는게아니라 그냥 새 액티비티가 열려버리는거라 네비게이션바에서 선택한 아이템?정보가 넘어가질 않았음.</p>
<p>SearchActivity에서의 네비게이션바는 Search가 선택되어있어야하는데 Home이 선택되어있는 불쾌한 경험을 하게되어버림 ㅋㅋ</p>
<p>그래서 그냥 무식하게 처음선택되어있는 아이템을 정해주는걸로 해결함</p>
<pre><code class="language-kotlin">navigateBar.selectedItemId = R.id.search</code></pre>
<p>이렇게 네비게이션바의 selectedItemId 를 지정해주면 된당~</p>
<h2 id="imageview에-gif-넣기">ImageView에 GIF 넣기</h2>
<p>Glide를 사용해서 넣을 수 있음</p>
<ol>
<li>build.gradle.kts(Module:app) 파일의 dependencies 부분에 라이브러리 추가해주고 싱크 해준다.</li>
</ol>
<pre><code>```kotlin
dependencies {
    implementation (&quot;com.github.bumptech.glide:glide:4.11.0&quot;)
    annotationProcessor (&quot;com.github.bumptech.glide:compiler:4.11.0&quot;)
    .
    그 외 라이브러리들...
    .
   }
```</code></pre><ol>
<li><p>res/raw 폴더 생성해서 적용할 gif 파일을 넣어준다.</p>
</li>
<li><p>해당 액티비티의 코틀린 파일에서 글라이드를 통해서 넣어준다!</p>
<pre><code class="language-kotlin"> var gif1 = findViewById&lt;ImageView&gt;(R.id.iv_gif_genre_exploration1)
         gif1.clipToOutline = true
         Glide.with(this).load(R.raw.citypop).into(gif1)</code></pre>
</li>
</ol>
<h2 id="sticky-scroll-view">Sticky Scroll View</h2>
<p>스포티파이 앱의 검색 탭을 스크롤해보면 검색탭이 스크롤되다가 화면 천장에 닿으면 그때부터는 스크롤되지않고 천장에 붙어있게 된다.</p>
<p>찾아보니 Sticky View , Sticky Scroll 등으로 부르는 것 같고, 뭐 외부라이브러리를 사용해서 구현할 수도 있다고 하는데 최대한 외부라이브러리를 안쓰고 하고 싶었음</p>
<p>scrollView와 sticky Header(위에 붙어있을 애) 만 있으면 그나마 편했을 것 같은데 나는 sticky Header 위에 또 다른 애가 하나 들어가있어서 걔는 그냥 그대로 위로 사라지고, sticky Header만 붙어있어야해서 좀 어지러웠다.</p>
<p>그리고 원래는 그냥 두개 다 스크롤 뷰에서 빼놔서 그것도 다시 수정해야했음 ㅎㅎ 귀찮아~~슈발</p>
<p>‘아무튼 그래서 결국 스크롤뷰에 top contents 랑 검색창을 넣어준다음에,</p>
<pre><code class="language-kotlin">        scrollView = findViewById(R.id.scroll_search_page2)
        stickyHeader = findViewById(R.id.layout_search_tab)
        topContents = findViewById(R.id.layout_top_contents)

        scrollView.viewTreeObserver.addOnScrollChangedListener {
            val  scrollY = scrollView.scrollY
            val topContentBottom = topContents.bottom
            if(scrollY &gt; topContentBottom) {
                stickyHeader.translationY = (scrollY - topContentBottom).toFloat()
            } else{
                stickyHeader.translationY = 0f
            }
        }</code></pre>
<p>이렇게  scrollView, 검색창, 위에 검색하기 등이 있는 부분을 각각 변수에 넣어줬음</p>
<p>viewTreeObserver 는 View가 화면에 그려진 뒤의 정보를 가지고 올 수 있게 해주는 역할임</p>
<p>addOnScrollChangedListener는 스크롤상태의 변경시의 정보를 가지고온다는 뜻</p>
<p>viewTreeObserver없이 높이를 가지고오면 뷰가 그려지기 전의 높이를 가져오게돼서 소용이 없다고함! 저렇게하면 스크롤됐을때의 해당 뷰의 높이를 구해올 수 있다..</p>
<p>그래서 스크롤뷰의 움직인 값을 scrollY로 설정해주고,</p>
<p>topContent의 아래의 값? 도 받아오게 해준다음에,</p>
<p>만약에 스크롤 움직인 값이 topContent의 Bottom보다 클때 검색창의 세로 이동을 고정시키게 해줬음.</p>
<p>양심고백하자면 식을 직접 짜려고 노력했으나 어떻게해야 내가 원하는 곳에 멈추게 하는지 알수가없어서 검색창이 스크롤되다가 멈추긴하는데 존나 엉뚱한데에 멈춰서버리는 불쾌한 경험을 견디지못하고.. 찾아갈 튜터님도 없어버려서 그냥 지피티한테 식 짜달라고 해버림…ㅜ.ㅜ 죄송합니다 죄송합니다 죄송합니다 너무 화나서 참을수가없엇어요.. 오늘은 주말이라 튜터님이 없자나여..ㅜ.ㅜ</p>
<h2 id="암시적-인텐트로-카메라-열기">암시적 인텐트로 카메라 열기</h2>
<p>를 하려고 열심히 도전했는데 실패함~! </p>
<p>암시적인텐트 처음써보는거기도한데 </p>
<p>카메라를 열려면 Manifest에서 권한 설정도 해줘야하고,</p>
<p>찍은 사진으로 어떤 액션을 취하려면 registerForActivityResult로 따로 설정도해줘야하는데 ㅈㄴ복잡해서 머리터질거같은데 꾹참고 블로그 글 보면서 따라해봤는데</p>
<p>다 되고 테스트해봤는데</p>
<p>카메라 버튼누르면 뭐 암시적인텐트 된거마냥 다른 앱 열겠냐는 창  떠서 와 성공? 했는데</p>
<p>에뮬레이터라서 그런가 이동안되고, 그 이후로 다시 재시작해서 카메라버튼눌러도 아무반응이없어버려서</p>
<p>열받아서 걍 싹 지워버림<del>~</del></p>
<p>그리고 그냥 암시적인텐트 카메라로 안하고 머 유투브 열기 그런거로 하기로 노선 변경함</p>
<p>주제 파악 잘해버리기~!</p>
<h2 id="오늘의-결과물">오늘의 결과물~!</h2>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/657b5fd5-68ba-4dd9-b489-a83c38957e8e/image.gif" alt=""></p>
<p>네비바 누르면 화면 이동하고, 검색탭의 gif랑 스티키 뷰가 잘 구현되어있는 모씁~~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[내배캠 Android 4기] TIL 0628]]></title>
            <link>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0628</link>
            <guid>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0628</guid>
            <pubDate>Sat, 29 Jun 2024 07:38:23 GMT</pubDate>
            <description><![CDATA[<p>오늘 할일</p>
<ul>
<li><input checked="" disabled="" type="checkbox"> 코드카타 50번</li>
<li><input checked="" disabled="" type="checkbox"> 스탠다드반 과제 다듬기</li>
<li><input disabled="" type="checkbox"> 람다식 공부</li>
</ul>
<hr>
<h2 id="코드카타">코드카타</h2>
<p><strong>⏲️ 09 : 20 ~ : 10 : 00</strong></p>
<p>오늘도 문제가 별로 안어려워서 구글링 안하고 풀었는데,</p>
<p>중간에 indexOf 만 일치하는 첫번째인덱스말고 마지막 인덱스 반환하게 할 수 있나만 궁금해서</p>
<p>검색해서 lastIndexOf를 찾아내서 잘 완료했당~!</p>
<p>근데 다른 사람 풀이보니까 람다식 천지인거보고 개빡침~!</p>
<p>무슨무슨법으로 람다식 금지시켜라;;</p>
<p>어케 푼건지 이해가 안되어버림~!</p>
<p><a href="https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-50-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-0im2h1l6">https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-50-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-0im2h1l6</a></p>
<hr>
<h2 id="스탠다드반-과제-다듬기">스탠다드반 과제 다듬기</h2>
<p>어제 작성해놓은 무조건 수정해야될것들!</p>
<p><strong>흐린눈하고 넘길 수 없는것</strong></p>
<ol>
<li>하단 네비게이션바? 하는 방법 알아내서 넣어야함</li>
<li>제일 밑에 Hyang 라디오부분에 위에 검은색 투명 그라디언트 추가해야함</li>
<li>Hyang 라디오 부분에 플레이리스트 미리듣기 버튼 양옆 패딩 값 줄이고, 투명도 조절</li>
</ol>
<p>어제 TIL을 끝까지 안썼는데 어제 네비바까지는 구현해놨기때문에~!</p>
<p>2번 3번 했음</p>
<h3 id="그라디언트-xml-작성해서-적용">그라디언트 xml 작성해서 적용</h3>
<ol>
<li><p>xml 파일 생성 후 코드 작성</p>
<pre><code class="language-kotlin"> &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;

 &lt;shape xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
     android:shape=&quot;rectangle&quot;&gt;

     &lt;gradient
         android:angle=&quot;270&quot;
         android:startColor=&quot;#CC000000&quot;
         android:centerColor=&quot;@android:color/transparent&quot;
         android:endColor=&quot;#99000000&quot;
         android:type=&quot;linear&quot;/&gt;

 &lt;/shape&gt;</code></pre>
<p> 이렇게 대충 gradient 태그에</p>
<p> 적용할 각도, 시작색, 중간색 끝 색 정하고, 그라디언트 타입 알맞은걸로 정해주면된다~!</p>
<p> 나는 그냥 linear로 위 아래는 검은색인데 투명도 살짝있는 검은색하고 중간부분은 아예 투명하게 줘서 사진이 잘보이는 걸 원해서~</p>
</li>
</ol>
<ol>
<li>적용할 image View src에 넣어주기~</li>
</ol>
<pre><code class="language-kotlin">                    &lt;ImageView
                        android:id=&quot;@+id/iv_radio_artist_photo_gradient&quot;
                        android:layout_width=&quot;match_parent&quot;
                        android:layout_height=&quot;match_parent&quot;
                        android:layout_marginTop=&quot;16dp&quot;
                        android:layout_marginStart=&quot;16dp&quot;
                        android:layout_marginEnd=&quot;16dp&quot;
                        android:src=&quot;@drawable/gradient_radio_artist_photo&quot;
                        /&gt;</code></pre>
<center class="half">
    <img src="https://velog.velcdn.com/images/orinugoori_art/post/9e546704-65ab-4c9e-ba23-e92cf4f640d1/image.png" width="300"/>
    <img src="https://velog.velcdn.com/images/orinugoori_art/post/fe66903d-eb8b-4944-a856-a2b890b5be40/image.png" width="300"/>
</center>


<p>그라디언트 적용 전후 비교~!</p>
<h3 id="미리듣기-버튼-여백-조절">미리듣기 버튼 여백 조절</h3>
<p>그냥 간단하게 원래 패딩값이 전체 10인가 들어가있었는데, </p>
<p>앞에는 이미지도 들어가있고해서 서로 여백이 다른게 너무 거슬려서 수정해줌~!</p>
<p>그리고 스크롤되는 화면의 크기가 너무 딱맞으니까 네비바 넣고 밑이 살짝 잘려서 보이게돼서</p>
<p>살짝 여유롭게 만들어서 끝까지내렸을 때는 네비바에 안가려지게 해줬당</p>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/be1c386c-c999-4805-b716-c98039d857e9/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/d2c76c04-2624-484a-b852-69ef2a248a5d/image.png" alt=""></p>
<p>전후 비교~!</p>
<p>첫번째거는 미리듣기 글자 뒤에 여백이 애매하게 넓어버림~!</p>
<hr>
<h2 id="튜터님한테-가서-피드백-듣고오기">튜터님한테 가서 피드백 듣고오기</h2>
<p>성희 튜터님한테 가서 지금까지 과제한거 들고가서 검사맡고 질문 + 수다를 떨고왔다</p>
<p>성희튜터님 너무조아…너무따수워..존내 힐링타임</p>
<ol>
<li><p>이미지 클리핑마스크 같은 기능이 있는지?</p>
<p> → clipToOutLine </p>
<p> api 31버전 이상에서는 xml파일에서도 사용가능하고 그 전 버전들은 kt파일에서 설정해줘야함</p>
<p> background에 마스크씌울 모양?을 넣어주고 src에 이미지 넣은다음에 clipToOutLine하면 마스크씌워져서 모양따라 된당</p>
</li>
</ol>
<ol>
<li><p>현업에서 저렇게 이미지를 넣는다고하면 디자인을 아예 해서 완성된 이미지를 넣는지, 따로 넣어서 코드로 만드는지?</p>
<p> 상황마다 효율마다 다르지만, 지금 내 앱을 만든다고 가정했을때 추천 스테이션 부분은 무조건 이미지 디자인해서 넣을거고 아티스트 이름, 로고 정도만 코딩으로 할거같고,</p>
<p> 믹스추천, 즐겨듣는 믹스 같은경우는 단순해서 따로 할 수 도 있을 것같다. 보통 그냥 디자인팀, 개발팀 상의 하에 효율적인 방법을 구상해서 결정함</p>
</li>
<li><p>이 이후에 더 내맘대로 추가해도 되는지?</p>
<p> 원한다면 ㄱㄱ why not?</p>
</li>
</ol>
<hr>
<h2 id="튜터님-피드백-반영해서-수정">튜터님 피드백 반영해서 수정</h2>
<h3 id="cliptooutline">clipToOutLine</h3>
<p>오늘 튜터님한테 물어봐서 존재를 알아낸 기능~!</p>
<p>포토샵의 클리핑 마스크 같은 기능이 있는지 여쭤봤는데 바로 알려주심</p>
<p>또 갓성희야..나는 숭배할 수바께없ㅇ…</p>
<p>원래도 내가 이게 가능한지 보려고 background에 oval shape xml을 넣어놓고,</p>
<p>src에 이미지 넣어서 되는지 확인했는데 안돼서 포기했었는데,,</p>
<p>여기서 clipToOutLine만 추가해주면 되는거였음~~!</p>
<p>완즈이 수정 간단해서 럭키비키바키자너~</p>
<p>다만 주의할 점으로 clipToOutLine을 xml에서 바로 적용할 수 있는건 </p>
<p>API31 이상부터고, 그 이전 버전에 적용하려면 코틀린파일에서 적용해줘야함.</p>
<p>api31이상 : </p>
<p>xml파일 적용할 위젯 태그내에서 바로 적용가능 , 디자인 뷰에서도 마스크 적용되는걸 확인할 수 있음</p>
<pre><code class="language-kotlin"> &lt;ImageView
                    android:id=&quot;@+id/iv_radio_artist_circle&quot;
                    android:layout_width=&quot;30dp&quot;
                    android:layout_height=&quot;30dp&quot;
                    android:background=&quot;@drawable/button_shape_profile&quot;
                    android:src=&quot;@drawable/iv_cover_playlist_hyang&quot;
                    android:clipToOutline=&quot;true&quot;
                    android:scaleType=&quot;fitCenter&quot;
                    android:layout_marginTop=&quot;16dp&quot;
                    android:layout_marginStart=&quot;16dp&quot;
                    app:layout_constraintTop_toBottomOf=&quot;@id/scrollView_user_mix&quot;
                    app:layout_constraintStart_toStartOf=&quot;parent&quot;/&gt;</code></pre>
<p>api 30 이하:</p>
<p>해당 Activity.kt 파일에서 객체 만들어서 .clipToOutLine = true로 설정해주면 됨</p>
<pre><code class="language-kotlin">        val radioArtistCircle = findViewById&lt;ImageView&gt;(R.id.iv_radio_artist_circle)

        radioArtistCircle.clipToOutline = true</code></pre>
<h3 id="apptint">app:tint</h3>
<p>이거는 튜터님한테 배워온건아니고 내가 즐겨듣는 믹스 부분에 들어갈 프레임을 색 바꿔서 저장하는걸 까먹어서 그냥 하나만 만들어놨었음 </p>
<p>근데 수정하기 귀찮아서 그냥 색 하나로 통일할까… 하고 흐린눈 하고 있었는데</p>
<p>clipToOutLine처럼 마스크까지 되는걸 보니까 색상 변경도 여기서 할 수 있을 것 같은 예감이 들어버림</p>
<p>그래서 대충 tint 겠거니 하고 android:tint 옵션을 줬는데 색상이 적용되는거임 ㄹㅈㄷ!</p>
<p>근데 코드에 빨간줄이 뜨면서 android:tint로 쓰지말고 app:tint쓰라고 윽박지름</p>
<p>그래서 뭘 잘못한지도 모르고 일단 잘못했다고 빌면서 app:tint로 바꿔줬더니 빨간줄 철회됐다.</p>
<p>따로 일러스트 안키고 쉽게 색상 변경을 해내버림<del>~</del>!</p>
<p>그리고 이미지소스 여러개 넣는거보다 이렇게 바꾸는게 리소스?도 덜 들지 않을까?</p>
<p>완즈이 일석이조잖아?</p>
<p>..</p>
<p>여기서는 그런 표현을 쓰지 않습니다.</p>
<left class="half">
    <img src="https://velog.velcdn.com/images/orinugoori_art/post/454f44a0-5772-4454-aea2-524b92c4f608/image.jpg" width="300"/>
    <img src="https://velog.velcdn.com/images/orinugoori_art/post/df59a39f-9563-4c89-9382-c3be122dd54f/image.png" width="300"/>
</left>


<hr>
<h2 id="다른-사람들-과제-힐끔대기">다른 사람들 과제 힐끔대기</h2>
<p>금요일이기도하고,,</p>
<p>과제를 어느정도 다 끝내고 이제 더 디벨롭하는건 내 선택사항이라서,,</p>
<p>집중이 안되길래 걍 다른 분들 과제 하는거 힐끔댐</p>
<p>오지랖 재밌어~ 짜릿해~</p>
<p>내 안에 음침맨이 살고있는지 내가 게임하는거보다 관전하는거 조아해서 맨날 게임도</p>
<p>디코에서 친구들 게임하는거 방송틀어달라고 해서 방송 보는게 더 재밌는데</p>
<p>과제도 남이 코딩하는거 켜달라고해서 구경하니까 잼있음</p>
<p>그래서 그냥 다른 분들꺼 구경하면서~~</p>
<p>내가 미리 겪었던 오류 나오면 신나서 설명하고 ,,</p>
<p>모르는거 같이 해결해보고~</p>
<p>어려운개념 내가 조금 알고있는거 설명해드리고 했당<del>~</del></p>
<p>냥냥짱뿌듯행~~</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 51 (두개 뽑아서 더하기)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-51-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-uz0o7rlj</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-51-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-uz0o7rlj</guid>
            <pubDate>Sat, 29 Jun 2024 07:06:25 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>수웅이는 매달 주어진 음식을 빨리 먹는 푸드 파이트 대회를 개최합니다. 이 대회에서 선수들은 1대 1로 대결하며, 매 대결마다 음식의 종류와 양이 바뀝니다. 대결은 준비된 음식들을 일렬로 배치한 뒤, 한 선수는 제일 왼쪽에 있는 음식부터 오른쪽으로, 다른 선수는 제일 오른쪽에 있는 음식부터 왼쪽으로 순서대로 먹는 방식으로 진행됩니다. 중앙에는 물을 배치하고, 물을 먼저 먹는 선수가 승리하게 됩니다.</p>
<p>이때, 대회의 공정성을 위해 두 선수가 먹는 음식의 종류와 양이 같아야 하며, 음식을 먹는 순서도 같아야 합니다. 또한, 이번 대회부터는 칼로리가 낮은 음식을 먼저 먹을 수 있게 배치하여 선수들이 음식을 더 잘 먹을 수 있게 하려고 합니다. 이번 대회를 위해 수웅이는 음식을 주문했는데, 대회의 조건을 고려하지 않고 음식을 주문하여 몇 개의 음식은 대회에 사용하지 못하게 되었습니다.</p>
<p>예를 들어, 3가지의 음식이 준비되어 있으며, 칼로리가 적은 순서대로 1번 음식을 3개, 2번 음식을 4개, 3번 음식을 6개 준비했으며, 물을 편의상 0번 음식이라고 칭한다면, 두 선수는 1번 음식 1개, 2번 음식 2개, 3번 음식 3개씩을 먹게 되므로 음식의 배치는 &quot;1223330333221&quot;이 됩니다. 따라서 1번 음식 1개는 대회에 사용하지 못합니다.</p>
<p>수웅이가 준비한 음식의 양을 칼로리가 적은 순서대로 나타내는 정수 배열 <code>food</code>가 주어졌을 때, 대회를 위한 음식의 배치를 나타내는 문자열을 return 하는 solution 함수를 완성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>2 ≤ <code>food</code>의 길이 ≤ 9</li>
<li>1 ≤ <code>food</code>의 각 원소 ≤ 1,000</li>
<li><code>food</code>에는 칼로리가 적은 순서대로 음식의 양이 담겨 있습니다.</li>
<li><code>food[i]</code>는 i번 음식의 수입니다.</li>
<li><code>food[0]</code>은 수웅이가 준비한 물의 양이며, 항상 1입니다.</li>
<li>정답의 길이가 3 이상인 경우만 입력으로 주어집니다.</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<p><strong>최종 코드</strong></p>
<pre><code class="language-kotlin">class Solution {
    fun solution(food: IntArray): String {
        var answer: String = &quot;&quot;
        var player1 :String = &quot;&quot;

        for (i in 1 ..food.size -1){
            val num = food[i] /2
            for(j in 1..num){
                player1 += i.toString()
            }
        }

        answer = player1 + &quot;0&quot; + player1.reversed()

        return answer
    }
}</code></pre>
<p><strong>풀이</strong></p>
<p>food 에 들어간 숫자들은</p>
<p>인덱스 0 : 물 (무조건 1개만있음)</p>
<p>그리고 칼로리 순으로 분류한 음식의 개수들임</p>
<p>food의 음식 개수를 토대로 새로운 배열을 만들어야하는데,</p>
<p>일단 물이 가운데에 들어가야하고,  각 음식별로 두명의 선수한테 똑같은 개수로 나눠야하니까 2로 나눈 몫만큼을 주면됨 그리고 일렬로 놓고 끝부터 먹는 방식이기 때문에 </p>
<p>한 선수의 분량을 만들고 그걸 그냥 중간에 0 놓고 순서 뒤집어서 주면된다.</p>
<p>그래서 일단 player1 이란 문자열 하나 만들어서</p>
<p>for문으로 인덱스 1부터 돌면서 </p>
<p>음식의 개수를 2로 나눈 몫을 num이라는 변수에 넣어주고,</p>
<p>한번 더 for문을 돌려서 num만큼 해당 인덱스를 player1의 문자열에 추가해줌</p>
<p>그리고 최종 리턴할 answer문자열에 player1 + 0(물) player1을 뒤집은 문자열 합쳐서 넣어주면 끝</p>
<hr>
<h3 id="다른-사람-풀이">다른 사람 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(food: IntArray): String {
        val sb = StringBuilder()
        for (i in 1..food.lastIndex) {
            repeat(food[i] / 2) { sb.append(i) }
        }
        val reversed = sb.reversed()
        sb.append(0)
        sb.append(reversed)
        return sb.toString()
    }
}</code></pre>
<p>같은 조 코드카타 리뷰? 할 때 우리팀 짱고수 분이 스트링 빌더라는게 있다고 알려주셨었는데,</p>
<p>여기서 나왔당~</p>
<p>근데 뭔지는 잘모름..ㅜ 나중에 공부해볼것</p>
<pre><code class="language-kotlin">class Solution {
    fun solution(food: IntArray): String {
        var answer: String = &quot;&quot;

        food.forEachIndexed { index, i -&gt; if(index != 0) for(i in 1 .. i / 2) answer += index }

        var temp = answer.reversed()
        answer = answer + &quot;0&quot; + temp

        return answer
    }
}</code></pre>
<p>forEach를 사용해서 했는데..</p>
<p>index랑 , i를 받아서 인덱스가 0이 아닐때만 for문 돌려서 i가 i/2 만큼일 때 answer에 인덱스를 더해줌</p>
<p>문제 접근 방식은 저랑 똑같은데 람다식을 쓰셧군용~</p>
<hr>
<h3 id="tmi">TMI</h3>
<p>옛날에 나보다 진도 빠른 팀원 분이 이거 풀었다고 보여주실 때는
문제 길이 너무 길어보여서 와.. ㅅㅂ저거어케풀어야함 했는데
막상 또 풀때 돼서 푸니까 쉬워서 신남<del>~
열심히 공부햇더니 쪼끔씩 똑똑해지고있나봄</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 50 (두개 뽑아서 더하기)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-50-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-0im2h1l6</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-50-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-0im2h1l6</guid>
            <pubDate>Sat, 29 Jun 2024 07:04:28 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>문자열 <code>s</code>가 주어졌을 때, <code>s</code>의 각 위치마다 자신보다 앞에 나왔으면서, 자신과 가장 가까운 곳에 있는 같은 글자가 어디 있는지 알고 싶습니다.</p>
<p>예를 들어, <code>s</code>=&quot;banana&quot;라고 할 때,  각 글자들을 왼쪽부터 오른쪽으로 읽어 나가면서 다음과 같이 진행할 수 있습니다.</p>
<ul>
<li>b는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.</li>
<li>a는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.</li>
<li>n은 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.</li>
<li>a는 자신보다 두 칸 앞에 a가 있습니다. 이는 2로 표현합니다.</li>
<li>n도 자신보다 두 칸 앞에 n이 있습니다. 이는 2로 표현합니다.</li>
<li>a는 자신보다 두 칸, 네 칸 앞에 a가 있습니다. 이 중 가까운 것은 두 칸 앞이고, 이는 2로 표현합니다.</li>
</ul>
<p>따라서 최종 결과물은 [-1, -1, -1, 2, 2, 2]가 됩니다.</p>
<p>문자열 <code>s</code>이 주어질 때, 위와 같이 정의된 연산을 수행하는 함수 solution을 완성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>1 ≤ <code>s</code>의 길이 ≤ 10,000<ul>
<li><code>s</code>은 영어 소문자로만 이루어져 있습니다.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<p><strong>최종 코드</strong></p>
<pre><code class="language-kotlin">class Solution {
    fun solution(s: String): MutableList&lt;Int&gt; {

        var answer = mutableListOf&lt;Int&gt;()
        var sList = s.trim().toList()
        var validList = mutableListOf&lt;Char&gt;()
        var validIndex : Int = 0

        for(index in 0 .. sList.size-1){
            if(validList.isEmpty()){
                validList.add(sList[index])
                answer.add(-1)
            }else{
                if(validList.contains(sList[index])){
                    validIndex = validList.lastIndexOf(sList[index])
                    answer.add(index-validIndex)
                    validList.add(sList[index])
                }else{
                    answer.add(-1)
                    validList.add(sList[index])
                }
            }
        }
        return answer
    }
}</code></pre>
<p><strong>풀이 과정</strong></p>
<p>validList라는 mutableList를 만들어서 </p>
<p>sList의 인덱스를 하나씩 검사할때마다 검사한 애를 넣어주고,</p>
<p>만약에 validList에 sList지금 검사하는 애가 이미 들어있으면, 그 친구의 가장 마지막 인덱스를 찾아와서</p>
<p>answer에 넣어주는 식?</p>
<hr>
<h3 id="다른-사람-풀이">다른 사람 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(s: String): List&lt;Int&gt; {
        return s.withIndex().map { (i, c) -&gt; s.slice(0 until i).lastIndexOf(c).let { if (it &gt;= 0) i - it else -1 } }
    }
}</code></pre>
<p>또 대다식이야..(람다식이라는뜻)난 모른척할 수밖에 없어..</p>
<p>람다식 빨리 공부해야되는데,, 나중에 람다식 공부해서 이해다하고 나면 이게 바로 읽힐까?ㅜ</p>
<pre><code class="language-kotlin">class Solution {
    fun solution(s: String): IntArray {
        val answer = IntArray(s.length) {-1}
        val checkIndex = (&#39;a&#39;..&#39;z&#39;).associate { it to -1 } as HashMap

        s.forEachIndexed { i, v -&gt;
            if (checkIndex[v]!! &gt; -1) answer[i] = (i - checkIndex[v]!!)
            checkIndex[v] = i
        }

        return answer

    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[내배캠 Android 4기] TIL 0627]]></title>
            <link>https://velog.io/@orinugoori_art/TIL-0627</link>
            <guid>https://velog.io/@orinugoori_art/TIL-0627</guid>
            <pubDate>Thu, 27 Jun 2024 13:54:21 GMT</pubDate>
            <description><![CDATA[<p>오늘 할일 </p>
<ul>
<li><input checked="" disabled="" type="checkbox"> 코드카타 49번</li>
<li><input checked="" disabled="" type="checkbox"> 스탠다드반 과제</li>
<li><input disabled="" type="checkbox"> 람다식 공부</li>
</ul>
<hr>
<h2 id="코드카타">코드카타</h2>
<p><strong>⏲️ 09 : 10 ~ 09 : 30</strong></p>
<p>오늘 문제도 쉬워서 금방 풀었당~~</p>
<p>다른 사람 풀이를 보면서는 distinct()라는 함수로 배열이나 리스트의 중복을 제거해줄 수 있다는걸 배웠당~</p>
<hr>
<h1 id="스탠다드-반-과제">스탠다드 반 과제</h1>
<p><strong>⏲️10 : 20 ~ 13 : 20</strong></p>
<h2 id="튜터님한테-질문">튜터님한테 질문</h2>
<p>일단 어제 궁금했던 것들을 물어보러 갔다옴!</p>
<p><strong>질문 정리</strong></p>
<p>Q1. 위에 버튼들 (전체, 음악, 팟캐스트) 를 스크롤안되고 상단에 고정되게 하는방법</p>
<p>A1. 그 버튼들을 스크롤뷰에서 빼주면 됨.</p>
<p>그리고 저런 UI는 Button보다 Chip 이라는걸 알아보고 사용하는게 더 좋아보임!</p>
<p>Q2. 지금 코드 1000줄이 넘어가는데 이렇게 하는거 맞는가</p>
<p>A2. 지금은 리사이클 뷰나 프래그먼트 같은거 없이 작성하는거라 당장 단계에서는 이렇게 하는게 맞다. 나중에 저것들을 각각의 레이아웃으로 따로 빼주고 하면 간단해질것</p>
<h2 id="상단-버튼들-chip으로-변경하고-스크롤뷰-밖으로-빼주기">상단 버튼들 Chip으로 변경하고 스크롤뷰 밖으로 빼주기</h2>
<p>튜터님이 알려주신대로 상단 버튼들을</p>
<p>스크롤뷰 밖으로 빼서 스크롤하더라도 항상 상단에 보이도록 하고,</p>
<p>Button → Chip으로 변경해줌</p>
<ul>
<li><p>트러블 슈팅</p>
<h3 id="button-→-chip으로-변경할-때">Button → Chip으로 변경할 때</h3>
<h3 id="적용-테마를-material로-바꾸는-과정에서-생긴-문제">적용 테마를 Material로 바꾸는 과정에서 생긴 문제</h3>
<ol>
<li>어제 버튼 색상을 변경하기위해서 적용 테마를 Meterial → AppCompat으로 바꿨었는데, Chip을 사용하려고보니 각각의 Chip앞에 체크박스가 있는데 그게 지워지질 않음</li>
<li>열심히 검색해서 해결방법대로 해봐도 적용안됨.</li>
<li>더 찾아보니 AppCompat에서는 Chip의 속성이 제대로 적용되지 않을 수 있다고함</li>
<li>그래서 다시 Theme을 Meterial로 바꿔줌</li>
<li>그랬더니 버튼 색상이 또 안먹음</li>
</ol>
<p>  <strong>시도해본 것들</strong></p>
<ol>
<li><p>컬러값을 value에 지정해서 안하고 그냥 절대값으로 해서 그런가? 하고 color를 따로 지정해봄 </p>
<p>  → 소용 없음</p>
</li>
<li><p>buttonstyle을 하나 만들어줌</p>
<pre><code class="language-kotlin">     &lt;style name=&quot;profile_button&quot;
         &lt;item name=&quot;android:background&quot;&gt;@drawable/button_shape_profile&lt;/item&gt;
         &lt;item name=&quot;fontFamily&quot;&gt;@font/gotham_bold&lt;/item&gt;
         &lt;item name=&quot;android:textColor&quot;&gt;@color/black&lt;/item&gt;
         &lt;item name=&quot;android:textSize&quot;&gt;20sp&lt;/item&gt;
     &lt;/style&gt;</code></pre>
<p> → 소용없음</p>
</li>
<li><p>2번에 backgroundTint 옵션까지 넣어봄</p>
<p> → 소용없음</p>
</li>
<li><p>만든 버튼 스타일을 Theme에 넣어봄</p>
<p> →소용없음</p>
</li>
<li><p>그 외 이것저것..</p>
</li>
</ol>
<p>  <strong>해결한 방법</strong></p>
<p>  스타일에 parent로 내가 지금 적용한 테마를  주고,</p>
<p>  backgroundTint옵션을 @null 로 설정함!!!!!!</p>
<pre><code class="language-kotlin">      &lt;style name=&quot;profile_button&quot; parent=&quot;Widget.MaterialComponents.Button&quot;&gt;
          &lt;item name=&quot;android:background&quot;&gt;@drawable/button_shape_profile&lt;/item&gt;
          &lt;item name=&quot;backgroundTint&quot;&gt;@null&lt;/item&gt;
          &lt;item name=&quot;fontFamily&quot;&gt;@font/gotham_bold&lt;/item&gt;
          &lt;item name=&quot;android:textColor&quot;&gt;@color/black&lt;/item&gt;
          &lt;item name=&quot;android:textSize&quot;&gt;20sp&lt;/item&gt;
      &lt;/style&gt;</code></pre>
</li>
</ul>
<p>Chip 선택한애만 초록색으로 표시되게 만들기</p>
<p>chip이 알아야될게 은근 있는 느낌이라 자세하게 당장 완벽하게 파악하기는 쫌 빡세보임..아직 갈길이 머니까 일단은 당장 필요한 기능만 찾아서 했음</p>
<ol>
<li><p>선택했을때 색상이 변경되는 칩의 종류를 파악</p>
<p> 해당 칩을 선택하면 색상이 변경되려면 filter 라는 종류를 사용해야함</p>
<p> 그래서 chipGroup 에 style로 필터칩을 적용해줌</p>
</li>
<li><p>selector를 사용해서 선택됐을때의 색상과 아닐때의 색상을 지정하는 xml 파일을 만들어줌</p>
<pre><code class="language-kotlin"> &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
 &lt;selector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
     &lt;item android:state_checked=&quot;true&quot; android:color=&quot;@color/green&quot;/&gt;
     &lt;item android:state_checked=&quot;false&quot; android:color=&quot;#252525&quot;/&gt;
 &lt;/selector&gt;</code></pre>
<p> 이런식으로 selector에서 아이템 속성? 을 state_checked로 해주면 된다.</p>
<p> 그리고 drawable 폴더가 너무 지저분해지는 것 같길래 res/color 폴더를 만들어줌</p>
</li>
<li><p>chip style에서 selector로 텍스트와 배경색 설정</p>
<pre><code class="language-kotlin">     &lt;style name=&quot;CustomChipStyle&quot; parent=&quot;Widget.MaterialComponents.Chip.Filter&quot;&gt;
         &lt;item name=&quot;chipBackgroundColor&quot;&gt;@color/chip_background&lt;/item&gt;
         &lt;item name=&quot;android:textColor&quot;&gt;@color/selector_chip_text&lt;/item&gt;
         &lt;item name=&quot;chipMinHeight&quot;&gt;40dp&lt;/item&gt;
         &lt;item name=&quot;chipStartPadding&quot;&gt;10dp&lt;/item&gt;
         &lt;item name=&quot;chipEndPadding&quot;&gt;10dp&lt;/item&gt;
         &lt;item name=&quot;chipIconVisible&quot;&gt;false&lt;/item&gt;
         &lt;item name=&quot;closeIconVisible&quot;&gt;false&lt;/item&gt;
         &lt;item name=&quot;checkedIconVisible&quot;&gt;false&lt;/item&gt;
     &lt;/style&gt;</code></pre>
</li>
</ol>
<h3 id="틀에-디테일한-이미지-텍스트-넣어주기">틀에 디테일한 이미지, 텍스트 넣어주기</h3>
<p><strong>⏲️ 14 : 10 ~ 16 : 40</strong> </p>
<p>틀은 대충 끝난 것같아서 디테일하게 이미지랑 텍스트를 그럴싸하게 넣어줬다.</p>
<p>거짓말로 상대를 가장 속이기 쉬운 방법은 진실을 섞는것..</p>
<p>진짜 내 플리에 있는 것들과.. Hyang을 섞어서…</p>
<p>마치 Hyang이 종내 유명해서 스포티파이에서 추천아티스트로 띄워주는 거마냥 만들었당.</p>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/d22a94c0-fa50-4b55-b418-cfabe90513dd/image.gif" alt=""></p>
<p>스크롤 잘되고.. 칩 클릭 잘되고~!</p>
<p>리아나 도자캣 어스윈드앤 파이어 사이에 향 잘들어가고~!</p>
<p>그럴싸하게 만들어졌당~!</p>
<p><strong>나와의 싸움에서 진 부분</strong></p>
<ol>
<li>추천 스테이션에서 원래 틀만 만들고 레이아웃으로 직접 배치해서 하려고했는데,,,노가다 작업너무 힘들어서 그냥 일러스트로 만들어서 이미지로 넣어버림 ㅎ.ㅎ 편하다</li>
<li>내가 즐겨듣는 믹스에서 원래 저 프레임? 색이 계속 바뀌는데 핑크색이 예뻐서 그냥 핑크로 통일함</li>
<li>마지막에 Hyang 라디오 같은게 몇개 더 있어야하는데 어차피 복붙인데 그럴 필요 있을까 ..? 자기합리화하고 한개만 넣음!</li>
<li>마지막 Hyang 라디오에 위쪽에 살짝 검은색으로 그라데이션 넣어야 실제랑 더 비슷한데.. 귀찮아서 안함.</li>
</ol>
<hr>
<h3 id="오리너구리-월드-과제-제출">오리너구리 월드 과제 제출</h3>
<p>⏲️<strong>16 : 40 ~ 17 : 00</strong></p>
<p>마지막으로 깃허브 설정 확인하고..</p>
<p>깃언제마지막으로 푸시했는지 기억안나서 그냥 한번 더 푸시하고</p>
<p>잘 돌아가는지 확인하고 과제를 제출했다!</p>
<p>맨날 과제 선택구현 마지막은 못 구현하고 제출했는데 드디어 선택구현까지 다 해서 제출했당</p>
<p>짱뿌듯함~!</p>
<hr>
<h3 id="스탠다드반-과제에-사용한-기술-이유-등등-정리">스탠다드반 과제에 사용한 기술, 이유, 등등 정리</h3>
<p>⏲️ <strong>17 : 00 ~ 17 : 30</strong></p>
<p>일단 개인 노션에 과제 뽐내기? 무조건 해야되는건진 모르겠지만 혹시 모르니까 일단 대충</p>
<p>사용한 레이아웃 , 위젯, 그 외 기술 종류들과 내가 사용한 이유를 간단하게 정리함.</p>
<p>그리고 약간 아예 다른거 시작하기에는 지금 시간이 애매해서 과제에서 더 손봐야할 곳들을 찾아서 정리함</p>
<p><strong>흐린눈하고 넘길 수 없는것</strong></p>
<ol>
<li>하단 네비게이션바? 하는 방법 알아내서 넣어야함</li>
<li>제일 밑에 Hyang 라디오부분에 위에 검은색 투명 그라디언트 추가해야함</li>
<li>Hyang 라디오 부분에 플레이리스트 미리듣기 버튼 양옆 패딩 값 줄이고, 투명도 조절</li>
</ol>
<p><strong>흐린눈하면 넘길 수 있지만 흥이난다면 할 것</strong></p>
<ol>
<li>각 카테고리? 별로 플레이리스트 개수가 3개씩만 넣었는데 너무 적음. .더 늘리는 반복 작업을할까말까~</li>
<li>내가 즐겨듣는 믹스에 프레임? 색깔 다양하게 수정할까말까..</li>
<li>추천 스테이션 이미지에 넣은 로고가.. 너무.. 작음.. 키울까 모른척 할까..</li>
<li>Hyang 라디오에 있는 케밥메뉴 아이콘이랑, 플러스 아이콘이 하얀색이여야하는데 회색임 ..ㅎ</li>
<li>프로필 버튼 색이 너무 찐핑 좀더 연해야함</li>
<li>chip 선택할때 셋중에 하나만 선택되게 해야하는데 지금 그냥 누르는대로 다선택됨 미쳣나</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 49 (두개 뽑아서 더하기)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-49-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-45vte0r4</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-49-%EB%91%90%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0-45vte0r4</guid>
            <pubDate>Thu, 27 Jun 2024 00:53:22 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>정수 배열 numbers가 주어집니다. numbers에서 서로 다른 인덱스에 있는 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 배열에 오름차순으로 담아 return 하도록 solution 함수를 완성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>numbers의 길이는 2 이상 100 이하입니다.<ul>
<li>numbers의 모든 수는 0 이상 100 이하입니다.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<p><strong>최종 코드</strong></p>
<pre><code class="language-kotlin">class Solution {
    fun solution(numbers: IntArray): IntArray{
        var answer = intArrayOf()
        var numberSet = mutableSetOf&lt;Int&gt;()

        for(i in 0 ..numbers.size-1){
            for(j in 0.. numbers.size-1){
                if(i!=j){
                    numberSet.add(numbers[i]+numbers[j])
                }
            }
        }

        answer = numberSet.sorted().toIntArray()

        return answer
    }
}</code></pre>
<p><strong>풀이과정</strong></p>
<p>오늘도 아주 간단했다 제공된 정수 배열에서 서로 다른 인덱스의 값을 더해서 나올 수 있는 경우의 수를 다 적으면 되는 문제!</p>
<p>걍 반복문으로 값들 더해주는데, 중복이 없어야되니깐 Set만들어서 알아서 중복 없애게 하면 간단~!</p>
<hr>
<h3 id="다른-사람-풀이">다른 사람 풀이</h3>
<pre><code class="language-kotlin">class Solution {
    fun solution(numbers: IntArray): IntArray {
        val list = numbers.toList()
        return list.withIndex().flatMap { i -&gt; list.withIndex().map { j -&gt; i to j } }
            .filter { it.first.index != it.second.index }
            .map { it.first.value + it.second.value }
            .toSortedSet()
            .toIntArray()
    }
}</code></pre>
<p>람다식으로 되어있는데다가… flatMap 까지 있어서 너무어려움!!!</p>
<p>흠..근데 아무튼 filter로 첫번째 인덱스랑 두번째 인덱스가 다른 애들만 걸러서 걔네의 값을 더한걸 새로운 컬렉션으로 만들어준다음에, toSortedSet()을 사용해서 중복을 제거해주면서 정렬해준 듯</p>
<pre><code class="language-kotlin">class Solution {
    fun solution(numbers: IntArray): IntArray {
        val answers: MutableList&lt;Int&gt; = arrayListOf()
        var sum: Int
        var i = 0
        var j = 0

        while (i &lt; numbers.size - 1) {
            j = i + 1
            while (j &lt; numbers.size) {
                sum = numbers[i] + numbers[j]
                answers.add(sum)
                j++
            }

            i++
        }

        answers.sort()
        return answers.distinct().toIntArray()
    }
}</code></pre>
<p>흠 일단 비슷한데 중복제거를 Set으로 안하고 distinct()라는 함수를 씀</p>
<p>distinct라는걸 처음 봐서 검색해봤는데 배열이나 리스트에서 중복된 값을 제거해주는 것 같음!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[내배캠 Android 4기] TIL 0626]]></title>
            <link>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0626</link>
            <guid>https://velog.io/@orinugoori_art/%EB%82%B4%EB%B0%B0%EC%BA%A0-Android-4%EA%B8%B0-TIL-0626</guid>
            <pubDate>Wed, 26 Jun 2024 16:12:48 GMT</pubDate>
            <description><![CDATA[<p><strong>오늘 할일</strong></p>
<ul>
<li><input checked="" disabled="" type="checkbox"> 코드카타 48번</li>
<li><input checked="" disabled="" type="checkbox"> 스탠다드반 수업</li>
<li><input checked="" disabled="" type="checkbox"> 스탠다드반 과제</li>
<li><input disabled="" type="checkbox"> 람다식 공부</li>
</ul>
<hr>
<h2 id="코드카타">코드카타</h2>
<p>⏲️ 09 : 10 ~ 10 : 00</p>
<p>오늘은 주어진 배열을 이중배열로 주어지는 조건에 따라서</p>
<p>특정 인덱스 부분만 가져와서 정렬하고 그안에 특정 인덱스만 반환하게 하면됐음~</p>
<p>처음에 조건 배열이 이중배열인지 몰라서 좀 헤맸는데</p>
<p>문제를 잘읽도록하자~!</p>
<p>뿌듯했던건 어제 데이터 클래스 공부하면서 구조분해 배운거 써먹었다!</p>
<p><a href="https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-48-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-%EB%A7%88%EC%9D%8C%EB%8C%80%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0">https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-48-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-%EB%A7%88%EC%9D%8C%EB%8C%80%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0</a></p>
<hr>
<h2 id="스탠다드반-수업">스탠다드반 수업</h2>
<p>⏲️ 11 : 00 ~ 12 : 40</p>
<p>오늘부터 드디어 황성희 튜터님이랑 스탠다드반 수업이 시작됐당~~!</p>
<p>성희튜터님 조아~!</p>
<p>성희 튜터님 얼굴 처음봤는데 그 멤버카드랑 아바타 봤을때 상상한 모습보다 너무 귀여우셨당..</p>
<p>실례가되려나..하지만 귀여우셧는걸..</p>
<p>엄마라고 불러도 된다고 하셔서 엄마라고 불러야지 다짐했다</p>
<p>성희튜터님 조아<del>~</del></p>
<p>근데 사실 실시간 수업으로 들으면 내가 집중력이 안좋아서 머리에 안남아버리긴하는데</p>
<p>그래도 성희튜터님 조아~~</p>
<p>오늘 수업은 첫수업인만큼 오티를 하고,,</p>
<p>스탠다드반 노션 페이지를 소개해주시고,,</p>
<p>코딩하다가 계층 구조 타고올라가서 확인하는 방법 같은거 소개해주시고..</p>
<p>그 에뮬레이터? 보면서 레이아웃 구조 볼수있는 방법 소개해주시고,, 하셨당</p>
<p>과제는 좋아하는 앱 레이아웃 클론 코딩 해보기~</p>
<p>재밌겠당 머하지?</p>
<hr>
<h2 id="스탠다드반-과제-구상">스탠다드반 과제 구상</h2>
<p>⏲️ 14 :00 ~ 14 : 30</p>
<p>과제를위해 구상을 해야함~!</p>
<aside>
💡 💛 **C L O N E - C O D I N G** 💛

<p><strong>1주차</strong> </p>
<ul>
<li><p>자신이 좋아하는 앱의 한 화면을 똑같이 따라 만들어 보세요.</p>
<p>   ex) 인스타그램, Youtube, Netflix, 당근 마켓, 계산기 등</p>
</li>
<li><p>다양한 Widget과 Layout을 활용해 보세요.
(ImageView, TextView, EditText, Button, ScrollView, LinearLayout, ConstraintLayout 등)</p>
</li>
<li><p>왜 그 Widget과 그 Layout을 선택했는지 뽐내기 시간에 설명해 주세요.</p>
</li>
</ul>
<p><strong>2주차</strong></p>
<ul>
<li><p>Activity를 두 개 이상 생성해 보세요.</p>
</li>
<li><p>Intent를 활용하여 명시적, 암묵적 Intent 동작을 각 1개씩 구현해 보세요.</p>
<p>  (전화 걸기, 사진 찍기, 갤러리 불러오기, 타 Activity의 결과 값 받아오기 등)</p>
</li>
<li><p><strong>7월 8일</strong>까지 뽐내기 갤러리에 제출하기 (구현된 화면 + Github 주소)</p>
</aside>

</li>
</ul>
<p>일단 1주차 먼저해야하는데~</p>
<p>좋아하는 앱을 먼저 골라야함!</p>
<p>머 만들지~~</p>
<p>많이 안하는 앱을 하고싶은디</p>
<p>그럼 배민은 탈락인거같고..</p>
<p>근데 배민하면 배민은 폰트 뿌려서 폰트까지 똑같이 할 수 있을 거같은데 아쉽기도하고?</p>
<p>숨고는 많이 안할 것같긴한데.. 먼가 못생김</p>
<p>스포티파이도 먼가 못생김</p>
<p>사클할까햇는데 사클은 또 너무 단순한거같기도하고</p>
<p>오케 골랐음 스포티파이 당첨!</p>
<p>적당히 복잡하면서 음악 앱이기도 하고~</p>
<hr>
<h2 id="스포티파이-디자인-소스-만들기">스포티파이 디자인 소스 만들기</h2>
<p>⏲️ <strong>14 : 30 ~ 15 : 30</strong></p>
<p>스포티 파이앱을 보고 만들면서 필요할거같은데 xml로는 못만들 애들을 일러스트로 만들어줌!</p>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/97ba7cb7-3db6-4fcc-bfe4-a2bd6d7c6c09/image.png" alt=""></p>
<p>대충 이런식으로 소스 만들어줌<del>!근데 내 생각대로 이걸 적용할 수 있을지는 아직 몰겠다</del></p>
<hr>
<h2 id="스포티파이-앱-레이아웃-만들기">스포티파이 앱 레이아웃 만들기</h2>
<p>⏲️ <strong>15 : 30 ~ 20 : 00 / 22 : 00 ~ 01 :00</strong></p>
<h3 id="해결-안되는-점">해결 안되는 점</h3>
<ol>
<li>위에 버튼이 화면 스크롤을 내려도 계속 쫓아와야하는데 어떻게 하는지 모름</li>
</ol>
<h3 id="궁금한-점-알아볼-것들">궁금한 점( 알아볼 것들)</h3>
<ol>
<li>스크롤 뷰 처음 써보는데 원래 constraintHeight_percent 사용해서 비율 조절했는데 이게 스크롤뷰로 계속 화면길이가 달라져서 일단은 max를 걸어놨는데,,이거 우째야될까</li>
<li>프래그먼트?인가 그거안쓰고 해서 그런가 코드가 진짜 아직 반도 안했는데 벌써 600줄 넘어가는데 이거 맞나? (+추가 이제 1000줄 넘어감)</li>
<li>네비게이션바? 디자인 어떻게 하는지..</li>
<li></li>
</ol>
<h3 id="어려웠다가-해결한-것">어려웠다가 해결한 것</h3>
<ol>
<li>스크롤 뷰가 잘 되다가 갑자기 안돼서 엄청 헤맴<ol>
<li>스크롤 뷰랑 내가 작업했던 컨스트레이아웃 사이에 리니어 레이아웃을 넣어주고, 리니어의 height을 wrap_content로 설정하고, 컨스트레이아웃 레이아웃의 크기를 절대값으로 주니까 해결됐음</li>
<li>이거때매 몇시간을 헤맸는지 모르겠네!!!!아오!!!!</li>
</ol>
</li>
</ol>
<h3 id="오늘-만든-결과물">오늘 만든 결과물</h3>
<p><img src="https://velog.velcdn.com/images/orinugoori_art/post/42ed292a-9494-4c77-aaae-e6394b233ca5/image.gif" alt=""></p>
<hr>
<h2 id="tmi">TMI</h2>
<p>오늘 3시반 부터 아무것도 안먹고..
스크럼시간이랑 중간에 곡 제목 짓느라 멈춘거 말고 안쉬고 과제했당<del>~
덕분에 많이 한듯</del>!!! 굿!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 CODEKATA 48 (K번째 수정렬)]]></title>
            <link>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-48-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-%EB%A7%88%EC%9D%8C%EB%8C%80%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-48-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-%EB%A7%88%EC%9D%8C%EB%8C%80%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 26 Jun 2024 16:10:06 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명"><strong>문제 설명</strong></h3>
<p>배열 array의 i번째 숫자부터 j번째 숫자까지 자르고 정렬했을 때, k번째에 있는 수를 구하려 합니다.</p>
<p>예를 들어 array가 [1, 5, 2, 6, 3, 7, 4], i = 2, j = 5, k = 3이라면</p>
<ol>
<li>array의 2번째부터 5번째까지 자르면 [5, 2, 6, 3]입니다.</li>
<li>1에서 나온 배열을 정렬하면 [2, 3, 5, 6]입니다.</li>
<li>2에서 나온 배열의 3번째 숫자는 5입니다.</li>
</ol>
<p>배열 array, [i, j, k]를 원소로 가진 2차원 배열 commands가 매개변수로 주어질 때, commands의 모든 원소에 대해 앞서 설명한 연산을 적용했을 때 나온 결과를 배열에 담아 return 하도록 solution 함수를 작성해주세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>array의 길이는 1 이상 100 이하입니다.</li>
<li>array의 각 원소는 1 이상 100 이하입니다.</li>
<li>commands의 길이는 1 이상 50 이하입니다.</li>
<li>commands의 각 원소는 길이가 3입니다.</li>
</ul>
<hr>
<h3 id="내-풀이">내 풀이</h3>
<p><strong>최종 코드</strong></p>
<pre><code class="language-kotlin">class Solution {
    fun solution(array: IntArray, commands: Array&lt;IntArray&gt;): List&lt;Int&gt; {
        var answer = mutableListOf&lt;Int&gt;()

        for(command in commands){
            val (i, j, k) = command
            val newArray = array.sliceArray(i-1 until j).sorted()
            answer.add(newArray[k-1])
        }
        return answer
    }
}</code></pre>
<p><strong>풀이 과정</strong></p>
<p>처음에는 문제 또 제대로 안읽어서 이중배열인지모르고 풀려고하다가 안돼서 왜안돼슈발하고 읽어보니까 이중배열이였음~!</p>
<p>그래서 for문으로 commands안을 돌면서 뭘해야겠구나 했는데</p>
<p>어제 데이터클래스 공부하면서 구조분해 라는걸 공부했는데</p>
<p>그거 여기서는 못쓰나? 해서 찾아보니까 할 수 있는 것같았다.</p>
<p>그래서 commands의 행?을 돌면서 </p>
<p>구조분해해서 각 요소를 i j k 에 넣고 문제필요한데 필요한 곳에 잘썼다~개편한디?</p>
<hr>
<h3 id="다른-사람-풀이">다른 사람 풀이</h3>
<pre><code class="language-kotlin">class Solution {
        fun solution(array: IntArray, commands: Array&lt;IntArray&gt;): IntArray {
            return commands.map { command -&gt;
                array.slice(IntRange(command[0] - 1, command[1] - 1)).sorted()[command[2] - 1]
            }
                .toIntArray()
        }
    }</code></pre>
<p>어떤 사람은 .map을 이용해서 풀었당</p>
<p>근데 array.slice하고 .sorted()까지는 알겠는데 그다음에 냅다 바로 인덱스 넣어줄수도 있군</p>
<p>진짜 하다보면 이게 되나? 하고해보면 되는것들이 많아서 좀 재밌다</p>
]]></description>
        </item>
    </channel>
</rss>