2017-04-21 5 views
-3

Ruby에서이 예제를 해결하는 방법변환하는 방법 루비 바이트 "puts n"

왼쪽 시프트를 회전하고 값을 인쇄하십시오. X = 0x12345678

  • N = 4 → 0x23456781
  • N = 0x048D159E → 20 → 0x67812345
  • N = 2
  • rotate_left (부호 INT (X), 부호 숯 N) 와

    • 예. ..
  • +5

    출력을 설명하십시오. 왜 "left shift"를'x'로'4'를하면'0x23456781'이됩니까? '0x048D159E'는 어디에서 왔습니까? – Stefan

    +1

    @Stefan 하나의 퍼즐이 두 개 있습니다. 우선 알고리즘을 결정해야합니다. – mudasobwa

    +0

    도와 주시면 도와 드리겠습니다. –

    답변

    1

    달성하고자하는 것을 이해하는 것은 쉽지 않았습니다.

    def rotate_left(x, n) 
        x.to_s(2).rjust(32, '0').each_char.to_a.rotate(n).join.to_i(2) 
    end 
    

    훨씬 더 효율적인 대안이다 bitwise operations에만 적용 :

    본래의 접근법은, 그것이 32 길이로, 바이너리 문자열로 rotate it을 패드를 숫자로 변환하고 숫자로 다시 변환하는 것입니다 :

    • 레프트 n
      • 에 의해 x이 더 큰 그쪽 인 경우에 N 2 ** 32-1
      • 32 - n 의해 & 0xFFFFFFFF
    • 오른쪽 시프트 x 함께 절단 비트를 적용 또는 둘 메소드
      def rotate_left(x, n) 
          ((x << n) & (2**32 - 1)) | (x >> (32 - n)) 
      end 
      


    이들 두 숫자 사이 :

    [4, 20, 2].each do |l| 
        p rotate_left(0x12345678, l).to_s(16) 
    end 
    # "23456781" 
    # "67812345" 
    # "48d159e0" 
    

    마지막 출력은 이 아니라 "48d159e0"입니다. 더 많은 정보가 없으면 그것이 원하는 결과인지 알기가 어렵습니다.

    2

    숫자를 이진 문자열로 변환하여 랩 어라운드 이동을 수행합니다. 면책 조항 : 그것은 대단히 비효율적입니다.

    def rotate_left x, n 
        b = x.to_s(2).rjust(32, '0') 
        "#{b[n...b.length]}#{b[0...n]}".to_i(2) 
    end 
    
    # > "0x" + rotate_left(0x12345678), 4).to_s(16) 
    # => "0x23456781" 
    # 
    # > "0x" + rotate_left(0x12345678), 20).to_s(16) 
    # => "0x67812345" 
    # 
    # > "0x" + rotate_left(0x12345678), 20).to_s(16) 
    # => "0x48d159e0"