Skip to content

Instantly share code, notes, and snippets.

@starwing
Last active January 16, 2020 11:59
Show Gist options
  • Save starwing/6622f73e551e092184a3ba05f5aaefcb to your computer and use it in GitHub Desktop.
Save starwing/6622f73e551e092184a3ba05f5aaefcb to your computer and use it in GitHub Desktop.
Generate ID Code for some conditions
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[[
};
]]
--]=]
#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;
}
#/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