裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

2進化10進数の1の数

2018年02月10日 | ブログラミング

2進化10進数の1の数

締め切りが 2018/02/10 10:00 AM なので,その 1 分後に投稿されるように予約

コンピュータにおける数値の表現方式の一つに2進化10進数(BCD)があります。
これは、10進数の各桁をそのまま2進数に置き換えたものです。

例えば、42の場合、十の位の「4」を2進数で表して「0100」、一の位の「2」を2進数で表して「0010」なので、「0100 0010」となります。
(ここでは符号は考えないものとします。)

Nが与えられる時、N桁の整数を「2進数で表した時」と「2進化10進数で表した時」に、ビット列に含まれる「1」の数が等しいものがいくつあるかを求めてください。

例)
42は2進数では「101010」で3個、2進化10進数では「0100 0010」で2個なので対象外、
52は2進数では「110100」で3個、2進化10進数では「0101 0010」で3個なので対象です。

【入出力サンプル】

Input
2

Output
20

====================================

R には 整数を二進数に変換する intToBits があるので,以下のように簡単に書けるが,それでも 7 桁の整数を対象にすると 1 分以上かかる。Java で書くにしても,intToBits を実装すると実行時間 1 秒は切れない。

f = function(n) {
  bits = sapply(0:9, function(x) sum(intToBits(x) == 1))
  count = 0
  for (i in (10^(n-1)):(10^n-1)) {
    a = sum(bits[as.integer(unlist(strsplit(as.character(i), "")))+1])
    b = sum(intToBits(i) == 1)
    count = count + (a==b)
  }
  cat(count)
}

ある整数の二進表記に 1 が幾つ含まれるかは,オンライン整数列大辞典の A000120 である。これを使うと,前述のプログラムよりは速い。
Java で書き換えて,やっと 1 秒の壁をクリアできた。

# A002487 a(n+1) = (2*k+1)*a(n) - a(n-1) where k = floor(a(n-1)/a(n))
A002487 = function(n) {
  a = integer(n)
  a[1] = a[2] = 1
  for (i in 3:n) {
    k = floor(a[i-2]/a[i-1])
    a[i] = (2*k+1)*a[i-1]-a[i-2]
  }
  a
}
a = A002487(20)

# A007814
A007814 = function(n) {
  a = A002487(n+1)
  floor(head(a, -1)/a[-1])
}

# A000120
A000120 = function(n) {
  a = A007814(n)
  b = integer(n)
  b[1] = 1
  for (i in 2:n) {
    b[i] = b[i-1]+1-a[i-1]
  }
  b
}

f = function(n) {
  table = sapply(0:9, function(i) sum(intToBits(i) == 1))
  begin = 10^(n-1)
  end   = 10^n-1
  x = A000120(end)
  count = 0
  for (i in begin:end) {
    if (x[i] == sum(table[as.integer(unlist(strsplit(as.character(i), "")))+1])) {
      count = count+1
    }
  }
  cat(count)
}

f(2) # 20
f(3) # 200
system.time(f(4)) # 2054, 0.052 sec.
system.time(f(5)) # 13906, 0.600 sec.
system.time(f(6)) # 122756, 6.336 sec.
system.time(f(7)) # 1167892, 67.848 sec.

Java プログラム

import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    int n;
    if (false) {
      Scanner cin = new Scanner(System.in);
      String line;
      line = cin.nextLine();
      n = Integer.parseInt(line);      
      System.out.println(f(n));
    } else {
      System.out.println(f(2));
      System.out.println(f(3));
      System.out.println(f(4));
      System.out.println(f(5));
      System.out.println(f(6));
      long start = System.currentTimeMillis();
      System.out.println(f(7));
      long end = System.currentTimeMillis();
      System.out.println((end - start) + "ms");
    }
  }

  static void dump(int [] a) {
    for (int i = 0; i < a.length; i++) {
      System.out.print(a[i]+" ");
    }
    System.out.println();
  }

  static int [] a002487( int n) {
    int [] a = new int[n];
    a[0] = 0;
    a[1] = 1;
    for (int i = 2; i < n; i++) {
      int k = a[i-2]/a[i-1];
      a[i] = (2*k+1)*a[i-1]-a[i-2];
    }
    return a;
  }

  static int [] a007814( int n) {
    int [] a = a002487(n+1);
    int [] b = new int[n];
    for (int i = 0; i < n; i++) {
      b[i] = a[i]/a[i+1];
    }
    return b;
  }

  static int [] a000120(int n) {
    int [] a = a007814(n);
    int [] b = new int[n];
    b[0] = 0;
    for (int i = 1; i < n; i++) {
      b[i] = b[i-1]+1-a[i-1];
    }
    return b;
  }

  static int bitCount2(int i) {
    int count = 0;
    int [] bits = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2};
    while (i > 0) {
      count += bits[i % 10];
      i = i / 10;
    }
    return count;
  }

  static int f(int n) {
    int begin = (int)Math.pow(10, n-1);
    int end   = (int)Math.pow(10, n);
    int [] a = a000120(end);
    int count = 0;
    for (int i = begin; i < end; i++) {
      if (bitCount2(i) == a[i]) {
        count++;
      }
    }
    return count;
  }
}

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村