Problème CodeIQ 2812 "Rouge et Blanc". Pour un aperçu du problème, reportez-vous à Explication. En bref, vous pouvez afficher «1 << popcount (n)». Si vous résolvez en langage C
n;main(){scanf("%d",&n);n=!printf("%d\n",1<<__builtin_popcount(n));}
Cependant, il est nécessaire de concevoir d'appeler ce __builtin_popcount
autrement que C.
À la suite de l'enquête, il a été constaté que __sched_popcount ()
peut être utilisé sous Linux et __ popcountdi2 ()
peut être utilisé sur OS X.
La signature est ʻint __sched_popcount (size_t siz, long * a) , mais cela fonctionne pour le moment même si vous passez
(8, long long [1] {…})`. C'est parce que ce dernier est interprété comme ʻint [2] {…} ʻ dans un environnement 32 bits, et __sched_popcount renvoie la somme.
Pour appeler ces fonctions dans Ruby / Python / C #:
Le numéro magique 8 doit être évité si possible. Python est le plus précis car il dit 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)
Puisque Ruby de CodeIQ est 1.9.3, procédez comme suit. C'est sale parce qu'il a des variables globales, mais c'est inévitable.
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){
//Il n'y a aucun moyen de déterminer au moment de la compilation, alors commentez de manière appropriée
//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));
}
}
Si vous vous demandez si la surcharge de marshalling peut être plus importante, c'est probablement un succès. Utilisez cette méthode systématiquement.
Recommended Posts