CodeIQ 2812 "Red and White" Problem. For an overview of the problem, refer to Explanation. In short, you can output 1 << popcount (n)
.
If you solve in C language
n;main(){scanf("%d",&n);n=!printf("%d\n",1<<__builtin_popcount(n));}
However, it is necessary to devise to call this __builtin_popcount
from other than C.
As a result of the investigation, it was found that __sched_popcount ()
can be used on Linux and __popcountdi2 ()
can be used on OS X.
The signature is ʻint __sched_popcount (size_t siz, long * a) , but it works for the time being even if you pass
(8, long long [1] {…}) . This is because the latter is interpreted as ʻint [2] {…}
in a 32-bit environment, and __sched_popcount returns the sum.
In Ruby / Python / C #, to call these functions:
Magic number 8 should be avoided if possible. Python is the most accurate because it says ctypes.sizeof (ctypes.c_long)
.
#!/usr/bin/ruby
if RUBY_PLATFORM=~/linux/
if true
require 'fiddle'
__popcount_fn=Fiddle::Function.new(Fiddle::Handle::DEFAULT['__sched_cpucount'],[Fiddle::TYPE_INT,Fiddle::TYPE_VOIDP],Fiddle::TYPE_INT)
define_method(:popcount){|n|__popcount_fn.call(8,[n].pack('q'))}
else
require 'fiddle/import'
module LibC
extend Fiddle::Importer
dlload 'libc.so.6'
extern 'int __sched_cpucount(int,long long*)'
end
def popcount(n) LibC.__popcountdi2(8,[n]) end
end
elsif RUBY_PLATFORM=~/darwin/
if true
require 'fiddle'
__popcount_fn=Fiddle::Function.new(Fiddle::Handle::DEFAULT['__popcountdi2'],[Fiddle::TYPE_LONG],Fiddle::TYPE_INT)
define_method(:popcount){|n|__popcount_fn.call(n)}
else
require 'fiddle/import'
module LibC
extend Fiddle::Importer
dlload 'libSystem.dylib'
extern 'int __popcountdi2(long)'
end
def popcount(n) LibC.__popcountdi2(n) end
end
else
def popcount(n) n==0 ? 0 : popcount(n/2)+n%2 end
end
p 1<<popcount(gets.to_i)
Since Ruby of CodeIQ is 1.9.3, do as follows. It's dirty because it has global variables, but it's unavoidable.
require 'fiddle'
require 'dl'
$__popcount_fn=Fiddle::Function.new(DL::Handle::DEFAULT['__sched_cpucount'],[Fiddle::TYPE_INT,Fiddle::TYPE_VOIDP],Fiddle::TYPE_INT)
def popcount(n) $__popcount_fn.call(8,[n].pack('q')) end
#!/usr/bin/python
import sys,ctypes
if sys.version_info[0]>=3:
raw_input=input
xrange=range
if sys.platform.startswith('linux'):
libc=ctypes.cdll.LoadLibrary('libc.so.6')
popcount=lambda n:libc.__sched_cpucount(ctypes.sizeof(ctypes.c_long),(ctypes.c_long*1)(n))
elif sys.platform=='darwin':
libc=ctypes.cdll.LoadLibrary('libSystem.dylib')
popcount=lambda n:libc.__popcountdi2(n)
else:
popcount=lambda n:0 if n==0 else popcount(n/2)+n%2
print(1<<popcount(int(raw_input())))
using System;
using System.Runtime.InteropServices;
class CodeIQ2812{
[DllImport("msvcrt",CallingConvention=CallingConvention.Cdecl)]static extern int __popcountdi2(long n);
[DllImport("msvcrt",CallingConvention=CallingConvention.Cdecl)]static extern int __sched_cpucount(int n, long[] a);
static int popcount(long n){
//Comment out appropriately as there is no way to determine at compile time
//return __popcountdi2(n);
return __sched_cpucount(8,new long[]{n});
//return n==0 ? 0 : popcount(n/2)+(int)(n%2);
}
static void Main(){
int n=int.Parse(Console.ReadLine());
Console.WriteLine(1<<popcount(n));
}
}
If you're wondering if the marshalling overhead may be greater, it's probably a hit. Use this method systematically.
Recommended Posts