দ্রুততম আনুমানিক সাধারণ বিভাজক


13

সংক্ষিপ্ত বিবরণ

এই চ্যালেঞ্জে আপনাকে দুটি নম্বর দেওয়া হবে যা মাঝারি আকারের সংখ্যার একাধিকের চেয়ে দুটি ছোট অফসেট উভয়ই। আপনাকে একটি মাঝারি আকারের সংখ্যা আউটপুট করতে হবে যা একটি ছোট অফসেট বাদে প্রায় উভয় সংখ্যার বিভাজক।

জড়িত সংখ্যার আকার একটি অসুবিধা পরামিতি দ্বারা পরামিতি করা হবে l,। আপনার উদ্দেশ্যটি হ'ল l1 মিনিটের নিচে সবচেয়ে বড় পক্ষে সমস্যাটি সমাধান করা ।


সেটআপ

প্রদত্ত সমস্যায় একটি গোপন নম্বর pথাকবে, যা একটি এলোমেলো l^2( l*l) বিট নম্বর হবে। সেখানে দুটি গুণক q1, q2থাকবে, যা এলোমেলো l^3বিট সংখ্যা হবে এবং দুটি অফসেট r1, r2থাকবে, যা এলোমেলো lবিট সংখ্যা হবে।

আপনার প্রোগ্রামের ইনপুটটি x1, x2সংজ্ঞায়িত হবে :

x1 = p * q1 + r1
x2 = p * q2 + r2

পাইথনে পরীক্ষার কেস উত্পন্ন করার জন্য এখানে একটি প্রোগ্রাম রয়েছে:

from random import randrange
from sys import argv

l = int(argv[1])

def randbits(bits):
    return randrange(2 ** (bits - 1), 2 ** bits)

p = randbits(l ** 2)
print(p)
for i in range(2):
    q_i = randbits(l ** 3)
    r_i = randbits(l)
    print(q_i * p + r_i)

আউটপুট প্রথম লাইন একটি সম্ভাব্য সমাধান, যখন দ্বিতীয় এবং তৃতীয় লাইনগুলি আপনার প্রোগ্রামটি প্রদত্ত ইনপুট।


আপনার প্রোগ্রাম

প্রদত্ত x1, x2এবং l, আপনি একটি খুঁজে বের করতে হবে l^2বিট সংখ্যা p'যেমন যে x1 % p'এবং x2 % p'উভয় lবিট নম্বর। pঅন্যান্য সম্ভাবনা থাকতে পারে, যদিও সর্বদা কাজ করবে। সমাধান যাচাই করার জন্য এখানে একটি ফাংশন রয়েছে:

def is_correct(x1, x2, l, p_prime):
    p_prime_is_good = p_prime >> (l**2 - 1) and not p_prime >> l ** 2
    x1_is_good = (x1 % p_prime) >> (l-1) and not (x1 % p_prime) >> l
    x2_is_good = (x2 % p_prime) >> (l-1) and not (x2 % p_prime) >> l
    return bool(p_prime_is_good and x1_is_good and x2_is_good)

উদাহরণ

ধরুন l, জেনারেটর প্রোগ্রামটি একটি 9-বিট নম্বর বাছাই করে p, যা এই ক্ষেত্রে 442। জেনারেটরের 3জন্য দুটি বিট সংখ্যা বাছাই করে r1, r2, যা 4, 7। জেনারেটরের 27জন্য দুটি বিট সংখ্যা বাছাই করে q1, q2, যা 117964803, 101808039। কারণ এই পছন্দগুলি, x1, x2হয় 52140442930, 44999153245

আপনার প্রোগ্রামটি 52140442930, 44999153245ইনপুট হিসাবে দেওয়া হবে , এবং অবশ্যই একটি 9-বিট নম্বর ( পরিসীমাতে [256, 511]) আউটপুট করতে হবে 52140442930এবং 44999153245মডুলো যে 3 বিট নম্বর দেয় (পরিসীমাতে [4, 7])। 442এক্ষেত্রে একমাত্র এই জাতীয় মান, সুতরাং আপনার প্রোগ্রামটি আউটপুট করতে হবে 442


আরও উদাহরণ

l = 2
x1 = 1894
x2 = 2060
p = 11
No other p'.

l = 3
x1 = 56007668599
x2 = 30611458895
p = 424
No other p'.

l = 6
x1 = 4365435975875889219149338064474396898067189178953471159903352227492495111071
x2 = 6466809655659049447127736275529851894657569985804963410176865782113074947167
p = 68101195620
I don't know whether there are other p'.

l = 12
x1 = 132503538560485423319724633262218262792296147003813662398252348727558616998821387759658729802732555377599590456096450977511271450086857949046098328487779612488702544062780731169071526325427862701033062986918854245283037892816922645703778218888876645148150396130125974518827547039720412359298502758101864465267219269598121846675000819173555118275197412936184329860639224312426860362491131729109976241526141192634523046343361089218776687819810873911761177080056675776644326080790638190845283447304699879671516831798277084926941086929776037986892223389603958335825223
x2 = 131643270083452525545713630444392174853686642378302602432151533578354175874660202842105881983788182087244225335788180044756143002547651778418104898394856368040582966040636443591550863800820890232349510212502022967044635049530630094703200089437589000344385691841539471759564428710508659169951391360884974854486267690231936418935298696990496810984630182864946252125857984234200409883080311780173125332191068011865349489020080749633049912518609380810021976861585063983190710264511339441915235691015858985314705640801109163008926275586193293353829677264797719957439635
p = 12920503469397123671484716106535636962543473
I don't know whether there are other p'.

l = 12
x1 = 202682323504122627687421150801262260096036559509855209647629958481910539332845439801686105377638207777951377858833355315514789392768449139095245989465034831121409966815913228535487871119596033570221780568122582453813989896850354963963579404589216380209702064994881800638095974725735826187029705991851861437712496046570494304535548139347915753682466465910703584162857986211423274841044480134909827293577782500978784365107166584993093904666548341384683749686200216537120741867400554787359905811760833689989323176213658734291045194879271258061845641982134589988950037
x2 = 181061672413088057213056735163589264228345385049856782741314216892873615377401934633944987733964053303318802550909800629914413353049208324641813340834741135897326747139541660984388998099026320957569795775586586220775707569049815466134899066365036389427046307790466751981020951925232623622327618223732816807936229082125018442471614910956092251885124883253591153056364654734271407552319665257904066307163047533658914884519547950787163679609742158608089946055315496165960274610016198230291033540306847172592039765417365770579502834927831791804602945514484791644440788
p = 21705376375228755718179424140760701489963164

স্কোরিং

উপরে উল্লিখিত হিসাবে, আপনার প্রোগ্রামের স্কোরটি সর্বোচ্চ l1 যা প্রোগ্রামটি 1 মিনিটের নীচে পূর্ণ হয়। আরও সুনির্দিষ্টভাবে, আপনার প্রোগ্রামটি lএটির সাথে 5 টি এলোমেলো দৃষ্টান্তে চালিত হবে এবং এটি অবশ্যই 5 মিনিটের নীচে গড়ে সময় সহ পুরো 5 টিতে একটি সঠিক উত্তর দিতে পারে। কোনও প্রোগ্রামের স্কোর এটি সর্বোচ্চ lসাফল্য অর্জন করবে । টাইব্রেকার এটার গড় সময় হবে l

কীসের স্কোরগুলি লক্ষ্য করা যায় তার একটি ধারণা দেওয়ার জন্য, আমি একটি খুব সাধারণ উদ্দীপনা সমাধানকারী লিখেছি। এটি 5 এর স্কোর পেয়েছে I আমি অনেক ফ্যানসিয়ার সলভার লিখেছি। ভাগ্যের উপর নির্ভর করে এটি 12 বা 13 এর স্কোর পেয়েছে।


বিস্তারিত

উত্তরের তুলনায় নিখুঁত তুলনামূলকতার জন্য, আমি ক্যাপাসিক স্কোর দেওয়ার জন্য আমার ল্যাপটপে সাবমিশনের সময় নেব। ভাগ্য কিছুটা হলেও কমিয়ে আনার জন্য আমি সমস্ত দাখিলের ক্ষেত্রেও এলোমেলোভাবে বেছে নেওয়া উদাহরণগুলি চালাব। আমার ল্যাপটপে 4 সিপিইউ রয়েছে, i5-4300U সিপিইউ @ 1.9 গিগাহার্টজ, র‌্যামের 7.5 জি।

আপনার নিজের সময়ের ভিত্তিতে অস্থায়ী স্কোর পোস্ট করতে নির্দ্বিধায়, কেবল এটি পরিষ্কার করুন যে এটি অস্থায়ী বা স্বীকৃত।


দ্রুততম প্রোগ্রামের জয় হোক!


অনুমানটি কি নিকটতম হতে হবে?
ইয়াতসি

@ টুকুএক্সএক্স যে কোনও l^2বিট সংখ্যা lউভয় সংখ্যার ফ্যাক্টর হওয়ার থেকে দূরে চলে works তবে সাধারণত একটাই আছে।
isaacg

এখানে কিছু অ্যালগোরিদম ধারণা সহ একটি গবেষণামূলক প্রবন্ধ: টাইগারপ্রিন্টস ক্লেমসন.ইডু / সিগি / । বিভাগ 5.1.1

I5-4300U 2 কোর (4 থ্রেড), না 4 কোর হয়েছে।
অ্যান্ডারস কাসের্গ

উত্তর:


3

মরিচা, এল = 13

src/main.rs

extern crate gmp;
extern crate rayon;

use gmp::mpz::Mpz;
use gmp::rand::RandState;
use rayon::prelude::*;
use std::cmp::max;
use std::env;
use std::mem::swap;

// Solver

fn solve(x1: &Mpz, x2: &Mpz, l: usize) -> Option<Mpz> {
    let m = l*l - 1;
    let r = -1i64 << l-2 .. 1 << l-2;
    let (mut x1, mut x2) = (x1 - (3 << l-2), x2 - (3 << l-2));
    let (mut a1, mut a2, mut b1, mut b2) = (Mpz::one(), Mpz::zero(), Mpz::zero(), Mpz::one());
    while !x2.is_zero() &&
        &(max(a1.abs(), b1.abs()) << l-2) < &x1 &&
        &(max(a2.abs(), b2.abs()) << l-2) < &x2
    {
        let q = &x1/&x2;
        swap(&mut x1, &mut x2);
        x2 -= &q*&x1;
        swap(&mut a1, &mut a2);
        a2 -= &q*&a1;
        swap(&mut b1, &mut b2);
        b2 -= &q*&b1;
    }
    r.clone().into_par_iter().map(|u| {
        let (mut y1, mut y2) = (&x1 - &a1*u + (&b1 << l-2), &x2 - &a2*u + (&b2 << l-2));
        for _ in r.clone() {
            let d = Mpz::gcd(&y1, &y2);
            if d.bit_length() >= m {
                let d = d.abs();
                let (mut k, k1) = (&d >> l*l, &d >> l*l-1);
                while k < k1 {
                    k += 1;
                    if (&d%&k).is_zero() {
                        return Some(&d/&k)
                    }
                }
            }
            y1 -= &b1;
            y2 -= &b2;
        }
        None
    }).find_any(|o| o.is_some()).unwrap_or(None)
}

// Test harness

fn randbits(rnd: &mut RandState, bits: usize) -> Mpz {
    rnd.urandom(&(Mpz::one() << bits - 1)) + (Mpz::one() << bits - 1)
}

fn gen(rnd: &mut RandState, l: usize) -> (Mpz, Mpz, Mpz) {
    let p = randbits(rnd, l*l);
    (randbits(rnd, l*l*l)*&p + randbits(rnd, l),
     randbits(rnd, l*l*l)*&p + randbits(rnd, l),
     p)
}

fn is_correct(x1: &Mpz, x2: &Mpz, l: usize, p_prime: &Mpz) -> bool {
    p_prime.bit_length() == l*l &&
        (x1 % p_prime).bit_length() == l &&
        (x2 % p_prime).bit_length() == l
}

fn random_test(l: usize, n: usize) {
    let mut rnd = RandState::new();  // deterministic seed
    for _ in 0..n {
        let (x1, x2, p) = gen(&mut rnd, l);
        println!("x1 = {}", x1);
        println!("x2 = {}", x2);
        println!("l = {}", l);
        println!("p = {}", p);
        println!("x1 % p = {}", &x1 % &p);
        println!("x2 % p = {}", &x2 % &p);
        assert!(is_correct(&x1, &x2, l, &p));
        let p_prime = solve(&x1, &x2, l).expect("no solution found!");
        println!("p' = {}", p_prime);
        assert!(is_correct(&x1, &x2, l, &p_prime));
        println!("correct");
    }
}

// Command line interface

fn main() {
    let args = &env::args().collect::<Vec<_>>();
    if args.len() == 4 && args[1] == "--random" {
        if let (Ok(l), Ok(n)) = (args[2].parse(), args[3].parse()) {
            return random_test(l, n);
        }
    }
    if args.len() == 4 {
        if let (Ok(x1), Ok(x2), Ok(l)) = (args[1].parse(), args[2].parse(), args[3].parse()) {
            match solve(&x1, &x2, l) {
                None => println!("no solution found"),
                Some(p_prime) => println!("{}", p_prime),
            }
            return;
        }
    }
    println!("Usage:");
    println!("    {} --random L N", args[0]);
    println!("    {} X1 X2 L", args[0]);
}

Cargo.toml

[package]
name = "agcd"
version = "0.1.0"
authors = ["Anders Kaseorg <andersk@mit.edu>"]

[dependencies]
rayon = "0.7.1"
rust-gmp = "0.5.0"

চালানোর জন্য

cargo build --release
target/release/agcd 56007668599 30611458895 3
target/release/agcd --random 13 5

সরকারী ফলাফল l = 13, গড়ে 41.53 এস সময় হয়। l = 14 গড়ে 2 মিটারের বেশি সময় নিয়েছে।
isaacg

2

গণিত, এল = 5

এখানে একটি দ্রুত 5 সমাধান

(l = #3;
a = #1 - Range[2^(l - 1), 2^l];
b = #2 - Range[2^(l - 1), 2^l];
Last@Intersection[
Flatten[Table[Select[Divisors@a[[i]], # < 2^l^2 &], {i, Length@a}],
 1],
Flatten[Table[Select[Divisors@b[[i]], # < 2^l^2 &], {i, Length@b}],
 1]]
) &

ইনপুট
[x1, x2, এল]

যাতে কেউ এটি পরীক্ষা করতে পারে, এখানে মূল জেনারেটর রয়েছে

l = 5;
a = RandomInteger[{2^(l^2 - 1), 2^(l^2)}]
b = RandomInteger[{2^(l^3 - 1), 2^(l^3)}];
c = RandomInteger[{2^(l - 1), 2^l - 1}];
f = RandomInteger[{2^(l^3 - 1), 2^(l^3)}];
g = RandomInteger[{2^(l - 1), 2^l - 1}];
x = a*b + c
y = a*f + g

এল মান রান, কোড চয়ন করুন এবং আপনি তিনটি নম্বর পাবেন।
ইনপুট হিসাবে এলের সাথে শেষ দুটি রাখুন এবং আপনার প্রথমটি পাওয়া উচিত


আমি এই সমাধানটিকে l = 5 এর স্কোর পেয়ে যাচাই করেছি। টাইব্রেকার হিসাবে টাইমিংয়ের দরকার পড়লে আমি সময় পারব।
isaacg

1

গণিত, এল = 12

ClearAll[l, a, b, k, m];
(l = #3;
a = #1 - Range[2^(l - 1), 2^l];
b = #2 - Range[2^(l - 1), 2^l];
k = Length@a;
m = Length@b;
For[i = 1, i <= k, i++, 
For[j = 1, j <= m, j++, If[2^(l^2 - 1) < GCD[a[[i]], b[[j]]],
 If[GCD[a[[i]], b[[j]]] > 2^l^2, 
  Print@Max@
    Select[Divisors[GCD[a[[i]], b[[j]]]], 
     2^(l^2 - 1) < # < 2^l^2 &]; Abort[], 
  Print[GCD[a[[i]], b[[j]]]];
  Abort[]]]]]) &

ইনপুট [এক্স 1, এক্স 2, এল]

যাতে কেউ এটি পরীক্ষা করতে পারে, এখানে মূল জেনারেটর রয়েছে

l = 12;
a = RandomInteger[{2^(l^2 - 1), 2^(l^2)}]
b = RandomInteger[{2^(l^3 - 1), 2^(l^3)}];
c = RandomInteger[{2^(l - 1), 2^l - 1}];
f = RandomInteger[{2^(l^3 - 1), 2^(l^3)}];
g = RandomInteger[{2^(l - 1), 2^l - 1}];
x = a*b + c
y = a*f + g

এল মানটি নির্বাচন করুন, কোডটি চালান এবং আপনি তিনটি নম্বর পাবেন।
ইনপুট হিসাবে এলের সাথে শেষ দুটি রাখুন এবং আপনার প্রথমটি পাওয়া উচিত


আমি যখন l = 12এটি দিয়ে পরীক্ষা করেছি তখন এটি একটি ভুল ফলাফল দিয়েছে। বিশেষত, ফলাফলকারী বিভাজকটি একটি 146-বিট সংখ্যা ছিল, যা খুব বড় large আমি মনে করি এটি ঠিক করার জন্য আপনার কেবলমাত্র একটি ছোট পরিবর্তন দরকার।
isaacg

আমি ব্যর্থ কেসটিকে উপরের চূড়ান্ত উদাহরণ হিসাবে যুক্ত করেছি। আপনার সমাধানকারী 3 * পি এর সমান উত্তর দিয়েছে যা কিছুটা বড় ছিল। আপনার কোডটি দেখে মনে হচ্ছে আপনি কেবলমাত্র আপনার আউটপুটে কমপক্ষে l^2বিট রয়েছে কিনা তা পরীক্ষা করে দেখেন , তবে এটির বেশিরভাগ l^2বিট রয়েছে কিনা তাও আপনার পরীক্ষা করতে হবে ।
isaacg

এটি একইভাবে পরীক্ষার ক্ষেত্রে ব্যর্থ হয়েছিল, এটি এখনও কাজ করছে না। আমি গাণিতিকের সাথে খুব বেশি পরিচিত নই, তবে দেখে মনে হচ্ছে এটি কোনও আউটপুট ছাড়াই বেরিয়েছে। আমি মনে করি সমস্যাটি হ'ল এটি খুব বড় একটি ফ্যাক্টর সন্ধান করছে এবং তারপরে কাঙ্ক্ষিত পরিসরে কোনও ফ্যাক্টরটির বিভাজন সন্ধান করার পরিবর্তে এটি কেবল এড়িয়ে চলেছে।
isaacg


অফিশিয়াল স্কোর এল = 12, গড় গড় সময় 52.7 এর সাথে। সাবাশ!
ইসাকাক

1

পাইথন, এল = 15, গড় সময় 39.9 সে

from sys import argv
from random import seed, randrange

from gmpy2 import gcd, mpz
import gmpy2

def mult_buckets(buckets):
    if len(buckets) == 1:
        return buckets[0]
    new_buckets = []
    for i in range(0, len(buckets), 2):
        if i == len(buckets) - 1:
            new_buckets.append(buckets[i])
        else:
            new_buckets.append(buckets[i] * buckets[i+1])
    return mult_buckets(new_buckets)


def get_products(xs, l):
    num_buckets = 1000
    lower_r = 1 << l - 1
    upper_r = 1 << l
    products = []
    bucket_size = (upper_r - lower_r)//num_buckets + 1
    for x in xs:
        buckets = []
        for bucket_num in range(num_buckets):
            product = mpz(1)
            for r in range(lower_r + bucket_num * bucket_size,
                           min(upper_r, lower_r + (bucket_num + 1) * bucket_size)):
                product *= x - mpz(r)
            buckets.append(product)
        products.append(mult_buckets(buckets))
    return products

def solve(xs, l):
    lower_r = 2**(l - 1)
    upper_r = 2**l
    lower_p = 2**(l**2 - 1)
    upper_p = 2**(l**2)

    products = get_products(xs, l)
    overlap = gcd(*products)
    candidate_lists = []
    for x in xs:
        candidates = []
        candidate_lists.append(candidates)
        for r in range(lower_r, upper_r):
            common_divisor = gcd(x-r, overlap)
            if common_divisor >= lower_p:
                candidates.append(common_divisor)
    to_reduce = []
    for l_candidate in candidate_lists[0]:
        for r_candidate in candidate_lists[1]:
            best_divisor = gcd(l_candidate, r_candidate)
            if lower_p <= best_divisor < upper_p:
                return best_divisor
            elif best_divisor > upper_p:
                to_reduce.append(best_divisor)
    for divisor in to_reduce:
        cutoff = divisor // lower_p
        non_divisors = []
        for sub_divisor in range(2, cutoff + 1):
            if any(sub_divisor % non_divisor == 0 for non_divisor in non_divisors):
                continue
            quotient, remainder = gmpy2.c_divmod(divisor, sub_divisor)
            if remainder == 0 and lower_p <= quotient < upper_p:
                return quotient
            if quotient < lower_p:
                break
            if remainder != 0:
                non_divisors.append(sub_divisor)

def is_correct(x1, x2, l, p_prime):
    p_prime_is_good = p_prime >> (l**2 - 1) and not p_prime >> l ** 2
    x1_is_good = (x1 % p_prime) >> (l-1) and not (x1 % p_prime) >> l
    x2_is_good = (x2 % p_prime) >> (l-1) and not (x2 % p_prime) >> l
    return bool(p_prime_is_good and x1_is_good and x2_is_good)

if __name__ == '__main__':
    seed(0)

    l = int(argv[1])
    reps = int(argv[2])

    def randbits(bits):
        return randrange(2 ** (bits - 1), 2 ** bits)

    for _ in range(reps):
        p = randbits(l ** 2)
        print("p = ", p)
        xs = []
        for i in range(2):
            q_i = randbits(l ** 3)
            print("q", i, "=", q_i)
            r_i = randbits(l)
            print("r", i, "=", r_i)
            x_i = q_i * p + r_i
            print("x", i, "=", x_i)
            xs.append(x_i)

        res = solve(xs, l)
        print("answer = ", res)
        print("Correct?", is_correct(xs[0], xs[1], l, res))

এই কোডটি এই তথ্যের উপর ভিত্তি করে তৈরি করা হয়েছে যে r এর সমস্ত সম্ভাব্য মানের জন্য x1 - r এর পণ্যটি পি এর একাধিক হতে হবে এবং x2 - r এর পণ্যও অবশ্যই হওয়া উচিত। বেশিরভাগ সময় দু'টি পণ্যের জিসিডি নিতে ব্যয় হয়, যার প্রতিটিতে প্রায় 60,000,000 বিট রয়েছে। Gcd, যার কেবল প্রায় 250,000 বিট রয়েছে, পি'র পরীক্ষার্থীদের নিষ্কাশনের জন্য আবার এক্সর প্রতিটি মানের সাথে আবার তুলনা করা হয়। যদি তারা কিছুটা বড় হয় তবে তাদের উপযুক্ত ব্যাপ্তিতে হ্রাস করতে ট্রায়াল বিভাগ ব্যবহৃত হয়।

এটি পাইথনের জিপিপি 2 লাইব্রেরির উপর ভিত্তি করে তৈরি করা হয়েছে, এটি জিএনইউ এমপি লাইব্রেরির জন্য একটি পাতলা মোড়ক, বিশেষত সত্যিকারের ভাল জিসিডি রুটিন রয়েছে।

এই কোডটি একক থ্রেডযুক্ত।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.