#30daysofelm 11일째: 다음 1의 2진수
25671 단어 elm
데모: https://ellie-app.com/bVDMsDcTnXMa1
편집: 다음날 나는
elm-binary
로 더 좋은 버전을 만들었다.만약 네가 바퀴를 재발명하는 것을 좋아한다면, 오늘의 판본은 여전히 매우 좋다.
오늘 프로젝트 정보
1. Int -> Next higher number with same 1 bits
1.2 Converting from int to binary
1.4 Finding corresponding binary numbers
사용자는 숫자를 입력한 후에 같은 1자리 숫자를 가진 다음 이진수를 찾아야 한다.
보통 나는 가방 하나icidasset/elm-binary를 사용하지만 나 자신에게 도전을 하고 처음부터 내가 필요로 하는 기능을 실현하기로 결정했다.
저도 비트 연산자를 어떻게 사용하는지 몰라서 오늘 대량의 재구성이 필요합니다!D
0. elm live를 사용하여 자동으로 다시 로드
나는 테스트가 끝나기 전에 CodeWars의 오류 메시지를 받지 않고 현지에서 나의 해결 방안을 테스트하는 것을 더욱 좋아한다.
elm reactor
파일을 저장할 때 자동으로 다시 불러오는 기능이 없어서 좀 짜증납니다.내가 이전에 한 것은
index.html
을 만들어서 Main에서 컴파일한 자바스크립트 파일을 인용하도록 하는 것이다.엘름: https://guide.elm-lang.org/interop/그런 다음 프로젝트 루트 디렉토리의 두 개의 독립 터미널에서 다음을 수행합니다.
nodemon --exec elm make src/Main.elm --output=main.js
live-server
elm-live
HTML 파일을 만들거나 Main을 컴파일하지 않아도 같은 결과를 얻을 수 있다는 것을 발견했다.엘름.npm i -g elm-live
elm-live src/Main.elm
1. Int-> 동일한 1위의 다음 숫자 이상
1.1 이진수란 무엇입니까?
바이너리를 읽을 때 오른쪽에서 왼쪽으로 읽습니다.
만약 네가 6자리의 숫자를 가지고 있다면: 10101010.모든 숫자는 이전의 숫자의 두 배를 곱한다.
(32 * 1)
+ (16 * 0)
+ (8 * 1)
+ (4 * 0)
+ (2 * 1)
+ (1 * 0)
= 42
1.2 정수에서 이진법으로 전환
0과 1로 구성된 문자열만 받아들일 수 있는 사용자 정의 형식을 만들어야 할 수도 있습니다. 아마도 가능할 것입니다.
더 간단한 해결 방안은 비트 연산자를 사용할 수 있지만, 나는 다음에 배울 것이다.
1.2.1 Quoka의 JavaScript 프로토타입 사용
JavaScript를 알면 이득을 볼 수 있다Quokka installed in VS Code.
편집기에서 이 값들을 실시간으로 볼 수 있습니다.
오늘 같은 프로젝트에 대해 저는 자바스크립트로 원형 디자인을 하는 것을 더욱 좋아합니다. 왜냐하면 Elm으로 원형 디자인을 하면 같은 실시간 피드백을 제공하지 않기 때문입니다(제가 알기로).
다음은 제가 사용하기 시작한 JavaScript 원형입니다.
const n = 42
const numberOfBits = countBits(n) // 6
const bitsArray = generateBits(numberOfBits) // [32, 16, 8, 4, 2, 1]
const { binaryNumber } = generateBinaryNumber(n, bitsArray) // 101010
const cheating = (n).toString(2) // 101010
function countBits(n, count = 0) {
if (n >= 1) {
return countBits(n / 2, count + 1)
}
return count
}
function generateBits(n) {
return [...Array(n)].map((_, i) => 2 ** i).reverse()
}
function generateBinaryNumber(number, bitArray) {
return bitArray.reduce((acc, curr) => {
if (acc.number >= curr) {
acc.number -= curr
acc.binaryNumber += "1"
} else {
acc.binaryNumber += "0"
}
return acc
}, { number, binaryNumber: "" })
}
1.2.2 숫자가 몇 자리예요?
int를 지정합니다. 비트 목록
[8, 4, 2, 1]
을 만들고 싶지만, 우선 int가 몇 자리인지 알아야 합니다.countBits : Float -> Int -> Int
countBits number count =
if number >= 1 then
countBits (number / 2) (count + 1)
else
count
함수를 처음 호출할 때 int를 전달합니다.if문장에서 2를 제외한 결과는 부동점입니다.또한 Elm에 기본 매개 변수 값이 없기 때문에count 변수를 현저하게 전달해야 합니다.하지만 일부 응용 프로그램 해결 방안이 있다고 생각합니다.
따라서 나는 반드시 이런 불공평한 방식으로 함수를 호출해야 한다.
countBits (toFloat 42) 0
1.2.3 생성 비트
generateBits : Int -> List Int
generateBits numberOfBits =
List.range 0 (numberOfBits - 1)
|> List.map (\n -> 2 ^ n)
|> List.reverse
[0, 1, 2, 3, 4, 5]
[1, 2, 4, 8, 16, 32]
[32, 16, 8, 4, 2, 1]
JavaScript에서 우리는
(42).toString(2)
를 작성할 수 있지만, 이것은 더욱 재미있다D1.2.4 바이너리 생성
나는 JS 솔루션이 일반적인 for 순환이 있다면 더욱 좋을 것이라고 생각한다. 그러나
reduce
매우 재미있다. Elm의 List.foldl
도 마찬가지다.type alias BinaryNumber =
{ tempNumber : Int, binaryNumber : String }
generateBinaryNumber : Int -> BinaryNumber
generateBinaryNumber number =
List.foldl
(\currentBit accumulator ->
if accumulator.tempNumber >= currentBit then
{ tempNumber = accumulator.tempNumber - currentBit
, binaryNumber = accumulator.binaryNumber ++ "1"
}
else
{ accumulator | binaryNumber = accumulator.binaryNumber ++ "0" }
)
{ tempNumber = number, binaryNumber = "" }
(generateBits (countBits (toFloat number) 0))
이곳의 단점은 내가 누적기binaryNumber
부분만 되돌아오는 것이 아니라는 것이다.내가 이렇게 할 수 있을 것 같은데?나중에 알게 될 거야.1.3 바이너리에서 정수로 변환
이번에는 재밌었어!42를 예로 들면, 우리는 두 개의 목록을 조합할 수 있다. 하나는 이진 숫자이고, 다른 하나는 비트이다.
이진 숫자:
[1, 0, 1, 0, 1, 0]
비트:[32, 16, 8, 4, 2, 1]
그것들은 곱할 수 있다. 우리는 int를 얻을 수 있지만, 우리는 어떻게 목록 1의 모든 숫자와 목록 2의 모든 숫자를 곱합니까?우리가 이전에 만든 함수를 사용하면 우리는 다음과 같은 것을 얻을 수 있다.
binaryToInt : String -> Int
binaryToInt binaryNumber =
let
bits =
generateBits <| String.length binaryNumber
digits =
String.toList binaryNumber
|> List.map String.fromChar
|> List.map String.toInt
|> List.map (Maybe.withDefault 0)
in
List.map2 (*) bits digits |> List.sum
digits
변수가 좀 지루해요.String.toInt
가 하나Maybe Int
로 되돌아오기 때문에 우리는 1000%의 파악을 해야 한다. 어떤 비inty도 전달되지 않는다Maybe.withDefault
.List.map2
선에 대해 흥분을 느꼈다D1.4 해당하는 이진수 찾기
1.4.1 동일한 수량의 1위
다음 1자리 숫자와 같은 숫자를 찾기 위해서는 초기 숫자가 몇 자리인지 알아야 한다.
그것의 2진법 표시 형식은 10101010으로 3개의 1을 포함한다.
getNumberOf1s : String -> Int
getNumberOf1s binaryNumber =
binaryNumber
|> String.toList
|> List.map (\char -> String.fromChar char)
|> List.filter (\c -> c == "1")
|> List.length
['1', '0', '1', '0', '1', '0']
["1", "0", "1", "0", "1", "0"]
["1", "1", "1"]
3
1.4.2 동일 또는 +1자리 숫자 모두 가져오기
임의의 긴 숫자 목록을 만드는 것은 무의미하다.
42(10101010)는 6자리이기 때문에 다음에 1이 세 번 나오는 숫자는 6자리 또는 7자리가 될 수 있다.
봐봐
101010
, 너는 이것이 또 다른 6자리 숫자라는 것을 알 수 있지만, 나는 너무 피곤해서 간단하고 우아한 방법을 생각해 내지 못한다.DgetWithNBitsOrNPlusOne : Int -> List String
getWithNBitsOrNPlusOne number =
let
min =
-1 + countBits (toFloat number) 0
max =
min + 2
in
List.range (2 ^ min) ((2 ^ max) - 1)
|> List.map generateBinaryNumber
|> List.map (\bn -> bn.binaryNumber)
42살, 우리가 말하고자 하는 것은List.range 32 127
|> -- [{tempNumber = ..., binaryNumber = "100000"}, ...]
|> -- ["100000", "100001", ..., "111111"]
elm-format
쓰지 말래요(countBits (toFloat number) 0) - 1
.max = min + 1
라고 하면 더 의미가 있지만 가장 낮은 숫자는 아무런 클릭도 받지 못했다. 이것은 내가 싫어하는 것이다.1.4.3 다음에 같은 1의 이진수를 얻는다
getFirstMatchingBinaryNumber : Int -> String
getFirstMatchingBinaryNumber n =
getWithNBitsOrNPlusOne n
|> List.filter
(\num ->
(getNumberOf1s num == getNumberOf1s (generateBinaryNumber n).binaryNumber)
&& (binaryToInt num > n)
)
|> List.head
|> Maybe.withDefault ""
우리는 이전부터 이진수의 범위를 얻었다.그런 다음 다음, 다음을 필터링(보존)합니다.
나는 99퍼센트가 프로그래밍을 통해 이 결론을 얻을 수 있는 더 간단한 방법이 있다고 확신한다.D
2. 결론
Maybe
유형은 적응하는 데 시간이 좀 걸린다.Quokka+자바스크립트는 원형 디자인에 적합합니다!
Reference
이 문제에 관하여(#30daysofelm 11일째: 다음 1의 2진수), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kristianpedersen/30daysofelm-day-11-next-binary-number-with-same-number-of-1-s-34gg텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)