Last active
January 16, 2020 11:59
-
-
Save starwing/6622f73e551e092184a3ba05f5aaefcb to your computer and use it in GitHub Desktop.
Generate ID Code for some conditions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
io.input "../../Downloads/area_code_2018.csv" | |
io.output "area_code.py" | |
local map = {} | |
for l in io.lines() do | |
local code = l:match "^%d%d%d%d%d%d" | |
if tonumber(code) % 1000 > 0 and not map[code] then | |
map[#map+1] = code | |
map[code] = true | |
end | |
end | |
io.write [[ | |
area_codes = [ | |
]] | |
table.sort(map) | |
for _, v in ipairs(map) do | |
io.write(v, ",\n") | |
end | |
io.write[[ | |
] | |
]] | |
--[=[ | |
io.output "area_code.h" | |
local map = {} | |
for l in io.lines() do | |
local code = l:match "^%d%d%d%d%d%d" | |
if tonumber(code) % 1000 > 0 and not map[code] then | |
map[#map+1] = code | |
map[code] = true | |
end | |
end | |
io.write [[ | |
#define AREA_CODE_COUNT ]]:write(#map):write[[ | |
int area_codes[] = { | |
]] | |
table.sort(map) | |
for _, v in ipairs(map) do | |
io.write(v, ",\n") | |
end | |
io.write[[ | |
}; | |
]] | |
--]=] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <limits.h> | |
#define BITS (sizeof(uint64_t) * CHAR_BIT) | |
#define SHIFT (BITS / 2) | |
#define MASK ((1ULL << SHIFT) - 1) | |
uint64_t umul(uint64_t a, uint64_t b, uint64_t *carry) { | |
uint64_t al = a & MASK, ah = a >> SHIFT; | |
uint64_t bl = b & MASK, bh = b >> SHIFT; | |
uint64_t s0 = al * bl, s1 = ah * bl, s2 = al * bh, s3 = ah * bh; | |
uint64_t m = (s1&MASK) + (s2&MASK) + (s0 >> SHIFT); | |
*carry = s3 + (s1 >> SHIFT) + (s2 >> SHIFT) + (m >> SHIFT); | |
return (m << SHIFT) | (s0 & MASK); | |
} | |
uint64_t umod(uint64_t al, uint64_t ah, uint64_t b) { | |
uint64_t xl = b, xh = 0; | |
#define LT(AL,AH,BL,BH) ((AH) < (BH) || ((AH) == (BH) && (AL) < (BL))) | |
while (!LT(al >> 1 | (ah & 1) << 63, ah >> 1, xl, xh)) { /* X <= A/2 */ | |
xh = (xh << 1) | (xl >> 63); /* X <<= 1 */ | |
xl <<= 1; | |
} | |
while (!LT(al, ah, b, 0)) { /* A >= B */ | |
if (!LT(al, ah, xl, xh)) { /* A >= X */ | |
ah -= xh + (al < xl ? 1 : 0); /* A -= X */ | |
al -= xl; | |
} | |
xl = (xl >> 1) | (xh & 1) << 63; | |
xh >>= 1; | |
} | |
#undef LT | |
return al; | |
} | |
uint64_t mulmod(uint64_t a, uint64_t b, uint64_t n) { | |
uint64_t hi; | |
uint64_t lo = umul(a, b, &hi); | |
return umod(lo, hi, n); | |
} | |
uint64_t powmod(uint64_t a, uint64_t b, uint64_t n) { | |
uint64_t r = 1; | |
for (; b; b >>= 1) { | |
if (b&1) r = mulmod(r, a, n); | |
a = mulmod(a, a, n); | |
} | |
return r; | |
} | |
int miller_test(uint64_t n) { | |
uint64_t i, j, a[] = {2,3,5,7,11,13,17,19,23,29,31,37}; | |
uint64_t d = n-1, r = 0; | |
while (!(d&1)) ++r, d >>= 1; | |
for (i = 0; i < sizeof(a)/sizeof(*a); ++i) { | |
uint64_t x = powmod(a[i], d, n); | |
if (x == 1 || x == n-1) | |
continue; | |
for (j = 1; j < r; ++j) | |
if ((x = mulmod(x, x, n)) == n - 1) | |
break; | |
if (j >= r) return 0; | |
} | |
return 1; | |
} | |
#include <stdio.h> | |
#include "../area_code.h" | |
typedef struct Ctx { | |
int cur_area_code; | |
int cur_year; | |
int cur_month; | |
int cur_day; | |
int cur_seq; | |
} Ctx; | |
int gen_area_code(Ctx *ctx) { | |
if (ctx->cur_area_code >= AREA_CODE_COUNT) | |
return ctx->cur_area_code = 0; | |
if (ctx->cur_area_code == 0) | |
while (area_codes[ctx->cur_area_code+1] / 1000 != 530) | |
++ctx->cur_area_code; | |
if (area_codes[++ctx->cur_area_code] / 1000 != 530) | |
return ctx->cur_area_code = 0; | |
return area_codes[ctx->cur_area_code]; | |
} | |
int gen_year(Ctx *ctx) { | |
if (ctx->cur_year >= 2020) return ctx->cur_year = 0; | |
if (ctx->cur_year == 0) return ctx->cur_year = 1949; | |
return ++ctx->cur_year; | |
} | |
int gen_month(Ctx *ctx) { | |
if (ctx->cur_month >= 12) return ctx->cur_month = 0; | |
return ++ctx->cur_month; | |
} | |
int gen_day(Ctx *ctx) { | |
const int max[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | |
if (ctx->cur_day >= max[ctx->cur_month-1]) return ctx->cur_day = 0; | |
return ++ctx->cur_day; | |
} | |
int gen_date(Ctx *ctx) { | |
if (gen_day(ctx) == 0) { | |
if (gen_month(ctx) == 0) { | |
if (gen_year(ctx) == 0) | |
return 0; | |
gen_month(ctx); | |
} | |
gen_day(ctx); | |
} | |
if (ctx->cur_month == 0) gen_month(ctx); | |
if (ctx->cur_year == 0) gen_year(ctx); | |
return ctx->cur_year * 10000 + ctx->cur_month * 100 + ctx->cur_day; | |
} | |
int gen_seq(Ctx *ctx) { | |
if (ctx->cur_seq > 990) | |
return ctx->cur_seq = 0; | |
return ++ctx->cur_seq; | |
} | |
uint64_t gen_code(Ctx *ctx) { | |
if (gen_seq(ctx) == 0) { | |
if (gen_date(ctx) == 0) { | |
if (gen_area_code(ctx) == 0) | |
return 0; | |
gen_date(ctx); | |
} | |
gen_seq(ctx); | |
} | |
if (ctx->cur_year == 0) gen_date(ctx); | |
if (ctx->cur_area_code == 0) gen_area_code(ctx); | |
uint64_t code = area_codes[ctx->cur_area_code] | |
* 1000000000000ULL; | |
code += ctx->cur_year * 100000000ULL; | |
code += ctx->cur_month * 1000000ULL; | |
code += ctx->cur_day * 10000ULL; | |
code += ctx->cur_seq * 10ULL; | |
return code; | |
} | |
int calc_verify(uint64_t v) { | |
uint64_t w = 1, r = 0; | |
while (v) v /= 10, w <<= 1, r = (r + (v%10)*w) % 11; | |
return (12 - r) % 11; | |
} | |
#include <string.h> | |
int main(void) | |
{ | |
Ctx ctx; | |
memset(&ctx, 0, sizeof(ctx)); | |
uint64_t code; | |
while ((code = gen_code(&ctx))) { | |
int v = calc_verify(code); | |
if (v >= 10) continue; | |
if ((code += v) % 60 != 35) | |
continue; | |
if (miller_test(code / 5) | |
&& miller_test((code - 1)/2) | |
&& miller_test((code - 2)/3) | |
&& miller_test((code - 3)/4)) | |
printf("%lld\n", code); | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#/usr/bin/env python3 | |
from Crypto.Util import number | |
from area_code import area_codes | |
class Ctx: | |
def gen_area_code(self): | |
for code in range(0, 10000): | |
yield 530000 + code | |
def gen_year(self): | |
for y in range(1949, 2021): | |
yield y | |
def gen_month(self): | |
for m in range(12): | |
yield m+1 | |
MONTH_DAY = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | |
def gen_day(self, m): | |
for d in range(self.MONTH_DAY[m-1]): | |
yield d+1 | |
def gen_date(self): | |
for y in self.gen_year(): | |
for m in self.gen_month(): | |
for d in self.gen_day(m): | |
yield y*10000 + m*100 + d | |
def gen_seq(self): | |
yield 1 | |
def gen_code(self): | |
for area in self.gen_area_code(): | |
for date in self.gen_date(): | |
for seq in self.gen_seq(): | |
yield (area * 1000000000000 + | |
date * 10000 + | |
seq * 10) | |
WEIGHT = [ 2, 4, 8, 5, 10, 9, 7, 3, 6, 1, 2, 4, 8, 5, 10, 9, 7 ] | |
def calc_verify(self, v): | |
i, r = 0, 0 | |
while True: | |
v //= 10 | |
if v == 0: break | |
r = (r + (v%10)*self.WEIGHT[i]) % 11 | |
i += 1 | |
return (12 - r) % 11 | |
def miller_test(n): | |
return number._rabinMillerTest(n, 10) | |
ctx = Ctx() | |
for code in ctx.gen_code(): | |
v = ctx.calc_verify(code) | |
if v >= 10: continue | |
code += v | |
if code % 60 != 35: | |
continue | |
if (miller_test(code // 5) | |
and miller_test((code - 1)//2) | |
and miller_test((code - 2)//3) | |
and miller_test((code - 3)//4)): | |
print(code) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment