#30일 12월 14일: 4차 코드 대전
34273 단어 elm
코드/데모: https://ellie-app.com/bWVYn3n7zXFa1
배경.
오늘 나는 https://www.codewars.com/에서 두 가지 난제를 해결하고 싶다
나는 11일째 되는 날 두 개를 만들었다.세 번째는 같은 1비트수를 가진 다음 2진수를 찾는 문제인데 이것이 결국 우리의 관심사가 되었다.
다음 두 개는 오늘 완성된 것으로 원형은 자바스크립트+Quokka in VS Code이다.
Elm 컴파일러처럼 CodeWars katas가 최종적으로 테스트를 통과했을 때 기분이 좋았고, 다른 사람들이 같은 문제를 어떻게 해결하는지 보는 것도 재미있었다.
3. Balanced number
4. Circle of numbers
1. 각 숫자의 제곱을
squareEveryDigit : Int -> Int
squareEveryDigit num =
num
|> String.fromInt
-- 1234 -> "1234"
|> String.split ""
-- "1234" -> ["1", "2", "3", "4"]
|> List.map (\s -> String.toInt s |> Maybe.withDefault 0)
-- ["1", "2", "3", "4"] -> [1, 2, 3, 4]
|> List.map (\n -> n * n)
-- [1, 2, 3, 4] -> [1, 4, 9, 16]
|> List.map String.fromInt
-- ["1", "4", "9", "16"]
|> String.join ""
-- "14916"
|> String.toInt
-- 14916
|> Maybe.withDefault 0
-- toInt returns a Maybe Int. In case the conversion doesn't work, we set 0 as the default.
2. 문자당 인덱스 +1회 반복
공백이 없는 문자열을 지정하고, 문자마다 인덱스를 +1회, 중간에 대시를 넣습니다.
“Abc”->“A-Bb-Ccc”
"크리스티안"-> "K-Rr-Iii-sss-Ttt-IIiii-AA-NNNN"
upperIfIndex0 : Int -> String -> String
upperIfIndex0 index character =
if index == 0 then
String.toUpper character
else
character
repeatIndexPlus1Times : Int -> String -> String
repeatIndexPlus1Times index character =
List.repeat (index + 1) character
|> List.indexedMap upperIfIndex0
|> String.join ""
accum : String -> String
accum s =
s
|> String.toLower
|> String.split ""
|> List.indexedMap repeatIndexPlus1Times
|> String.join "-"
색인 변수는 List.indexedMap
에서 나온다.
앞의 두 함수는 내연적일 수 있지만, 이것은 그것을 축소된 익명 혼란으로 만들 것이다.이 밖에 index2와character2 변수명도 보기에 좋지 않다.
accum : String -> String
accum s =
s
|> String.toLower
|> String.split ""
|> List.indexedMap
(\index character ->
List.repeat (index + 1) character
|> List.indexedMap
(\index2 character2 ->
if index == 0 then
String.toUpper character
else
character
)
|> String.join ""
)
|> String.join "-"
3. 균형 숫자
이것은 일련의 숫자 카타스의 첫 번째 부분이다.사용할 수 있는 Elm 버전이 없기 때문에 JavaScript로 제출한 다음 Elm에서 다시 만듭니다.
a=가운데 숫자 왼쪽의 모든 숫자의 총계
b=가운데 숫자 오른쪽에 있는 모든 숫자의 합계
959->True(9==9)
123321->True(1+2==2+1)
123320->False(1+2!=2+0)
다시 말하면
squareEveryDigit : Int -> Int
squareEveryDigit num =
num
|> String.fromInt
-- 1234 -> "1234"
|> String.split ""
-- "1234" -> ["1", "2", "3", "4"]
|> List.map (\s -> String.toInt s |> Maybe.withDefault 0)
-- ["1", "2", "3", "4"] -> [1, 2, 3, 4]
|> List.map (\n -> n * n)
-- [1, 2, 3, 4] -> [1, 4, 9, 16]
|> List.map String.fromInt
-- ["1", "4", "9", "16"]
|> String.join ""
-- "14916"
|> String.toInt
-- 14916
|> Maybe.withDefault 0
-- toInt returns a Maybe Int. In case the conversion doesn't work, we set 0 as the default.
공백이 없는 문자열을 지정하고, 문자마다 인덱스를 +1회, 중간에 대시를 넣습니다.
“Abc”->“A-Bb-Ccc”
"크리스티안"-> "K-Rr-Iii-sss-Ttt-IIiii-AA-NNNN"
upperIfIndex0 : Int -> String -> String
upperIfIndex0 index character =
if index == 0 then
String.toUpper character
else
character
repeatIndexPlus1Times : Int -> String -> String
repeatIndexPlus1Times index character =
List.repeat (index + 1) character
|> List.indexedMap upperIfIndex0
|> String.join ""
accum : String -> String
accum s =
s
|> String.toLower
|> String.split ""
|> List.indexedMap repeatIndexPlus1Times
|> String.join "-"
색인 변수는 List.indexedMap
에서 나온다.앞의 두 함수는 내연적일 수 있지만, 이것은 그것을 축소된 익명 혼란으로 만들 것이다.이 밖에 index2와character2 변수명도 보기에 좋지 않다.
accum : String -> String
accum s =
s
|> String.toLower
|> String.split ""
|> List.indexedMap
(\index character ->
List.repeat (index + 1) character
|> List.indexedMap
(\index2 character2 ->
if index == 0 then
String.toUpper character
else
character
)
|> String.join ""
)
|> String.join "-"
3. 균형 숫자
이것은 일련의 숫자 카타스의 첫 번째 부분이다.사용할 수 있는 Elm 버전이 없기 때문에 JavaScript로 제출한 다음 Elm에서 다시 만듭니다.
a=가운데 숫자 왼쪽의 모든 숫자의 총계
b=가운데 숫자 오른쪽에 있는 모든 숫자의 합계
959->True(9==9)
123321->True(1+2==2+1)
123320->False(1+2!=2+0)
다시 말하면
3.1 JavaScript 솔루션
사실 나는 이것에 대해 매우 만족한다.
이것들은 내가 좌우 수조를 얻어야 하는 인덱스 수다.
Array.slice(start, end)
는 start
에서 end
로 자르지만 end
는 포함되지 않는다.제공하지 않으면, 그룹의 끝까지만 슬라이스됩니다.
const a = [1, 2, 3, 4]
const b = [1, 2, 3, 4, 5]
console.log(a.slice(0, 1), a.slice(3)) // [1] [4]
console.log(b.slice(0, 2), b.slice(3)) // [1, 2] [4, 5]
Elm에서 새로 작성할 JavaScript 솔루션은 다음과 같습니다.function balancedNum(n) {
const digits = String(n).split("").map(Number)
if (digits.length <= 2) {
return "Balanced"
} else if (digits.length === 3) {
return digits[0] === digits[2] ? "Balanced" : "Not Balanced"
}
const oneIfEven = (1 - digits.length % 2)
const middleIndex1 = Math.floor(digits.length / 2) - oneIfEven
const middleIndex2 = Math.ceil(digits.length / 2) + oneIfEven
const left = digits.slice(0, middleIndex1)
const right = digits.slice(middleIndex2)
const sum = a => a.reduce((a, b) => a + b)
return sum(left) === sum(right) ? "Balanced" : "Not Balanced"
}
3.2 Elm 솔루션
isBalanced : Int -> String
isBalanced n =
-- Split digits into array
let
digits =
n
|> String.fromInt
|> String.split ""
|> List.map String.toInt
|> List.map (Maybe.withDefault 0)
|> Array.fromList
oneIfEven =
1 - modBy 2 (Array.length digits)
digitsLength =
toFloat (Array.length digits)
-- Determine where to slice into left and right arrays
middleIndex1 =
(digitsLength / 2 |> floor) - oneIfEven
middleIndex2 =
(digitsLength / 2 |> ceiling) + oneIfEven
left =
Array.slice 0 middleIndex1 digits
right =
Array.slice middleIndex2 (Array.length digits) digits
-- Summing and comparing left and right
resultForDigitsIs3 =
if Array.get 0 digits == Array.get 2 digits then
"balanced"
else
"not balanced"
leftSum =
Array.toList left |> List.sum
rightSum =
Array.toList right |> List.sum
result =
if digitsLength <= 2 then
"balanced"
else if digitsLength == 3 then
resultForDigitsIs3
else if leftSum == rightSum then
"balanced"
else
"not balanced"
in
String.fromInt n ++ " is " ++ result
목록이 아닌 그룹을 사용합니다. 왜냐하면 특정한 색인 값이 필요하기 때문입니다.아마도 성능 때문에 Elm 목록에 색인이 없습니까?
부서가
Int
에서 Float
로 바뀌는 것은 틀림없이 이상하게 느껴질 것이다. 그러나 내가 아는 바에 의하면 이것은 성능/신뢰성 문제이다. https://github.com/elm/compiler/blob/master/hints/implicit-casts.md4. 숫자 링
크기가 n인 원을 정하고 x와 반대되는 숫자를 되돌려줍니다.circleOfNumbers 10 2
반환7
:
다른 사람의 해결 방안을 고려하기 전에, 나는 나의 해결 방안이 결코 이상적이지 않다는 것을 안다. 왜냐하면 그것은 부동점 수학에 의존하기 때문이다.
브라우저 콘솔에 0.1 + 0.2
만 입력하면 내가 무슨 말을 하는지 볼 수 있습니다.:)
4.1 JavaScript 솔루션
다음은 기본적인 생각입니다.
const thisAngle = angles[x]
숫자 2를 반환하는 각도const otherAngle = (angles[x] + 180) % 360
반대 각도angles.indexOf(otherAngle)
는 상반된 각도의 지수를 제시했는데 우리의 예는7
이다.const precision = 8
function circleOfNumbers(n, x) {
const distance = 360 / n
const angles = [...Array(n)].map((_, i) => i * distance)
.map(n => Number(n.toFixed(precision)))
const thisAngle = angles[x]
const opposite = Number(
((thisAngle + 180) % 360)
.toFixed(precision)
)
return angles.indexOf(opposite)
}
4.2 Elm 솔루션
모든 전환과
Maybe.withDefault
는 다소 단조롭고 무미건조했지만 나는 성공했다.기존
indexOf
함수는 없지만 { index : Int, angle : Float }
목록을 통해 복사할 수 있습니다.JavaScript의
.toPrecision(n)
함수를 복사하는 데 myrho/elm-round 를 사용하고 있습니다.circleOfNumbers : Int -> Int -> Int
circleOfNumbers howManyNumbers numberToCheck =
let
distance =
360 / toFloat howManyNumbers
angles =
List.range 0 (howManyNumbers - 1)
|> List.map
(\index ->
{ index = index
, angle = Round.round 5 (toFloat index * distance)
}
)
thisAngle =
angles
|> List.filter (\angle -> angle.index == numberToCheck)
|> List.map (\record -> record.angle)
|> List.head
|> Maybe.withDefault ""
|> String.toFloat
|> Maybe.withDefault 0
otherAngleFloat =
thisAngle + 180
otherAngleOverflowString =
Round.round 5 <| otherAngleFloat - 360
otherAngleAsString =
Round.round 5 <| thisAngle + 180
otherIndex =
angles
|> List.filter
(\this ->
if otherAngleFloat < 360 then
this.angle == otherAngleAsString
else
this.angle == otherAngleOverflowString
)
|> List.map (\record -> record.index)
|> List.head
|> Maybe.withDefault 0
in
otherIndex
4.3 정기선
여기가 내가 코드워스를 좋아하는 곳이야.테스트를 통과하고 제출할 수 있도록 복잡한 해결 방안을 제시하면 다음과 같은 문제에 직면하게 될 것이다.
const circleOfNumbers = (n, x) => (x + n / 2) % n;
너무 예뻐요.D현재의 지식에 따르면, 이것은 Elm에서 간단하게 복제할 수 없습니다.mod와rements 함수는 int에만 적용되기 때문입니다.
이것은 더 간소화할 수 있지만 어쨌든 이전의 해결 방안보다 낫다.
circleOfNumbers2 : Float -> Float -> Float
circleOfNumbers2 n numberToFind =
let
num =
numberToFind + n / 2
result =
if num > n then
num - n
else
num
in
result
5. 요약
Int
에서 Float
사이의 스텔스 전환을 놓쳤다.Reference
이 문제에 관하여(#30일 12월 14일: 4차 코드 대전), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kristianpedersen/30daysofelm-day-14-four-codewars-katas-3nck텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)