2018/12/15

a020: 身分證檢驗

a020: 身分證檢驗


#include

/*
      A=10 台北市     J=18 新竹縣     S=26 高雄縣
      B=11 台中市     K=19 苗栗縣     T=27 屏東縣
      C=12 基隆市     L=20 台中縣     U=28 花蓮縣
      D=13 台南市     M=21 南投縣     V=29 台東縣
      E=14 高雄市     N=22 彰化縣     W=32 金門縣
      F=15 台北縣     O=35 新竹市     X=30 澎湖縣
      G=16 宜蘭縣     P=23 雲林縣     Y=31 陽明山
      H=17 桃園縣     Q=24 嘉義縣     Z=33 連江縣
      I=34 嘉義市     R=25 台南縣
*/
int map[] = { // 英文字轉成上述數字後,個位數*9+十位數
  1, // A
  10,// B
  19,// C
  28,// D
  37,// E
  46,// F
  55,// G
  64,// H
  39,// I
  73,// J
  82,// K
  2, // L
  11,// M
  20,// N
  48,// O
  29,// P
  38,// Q
  47,// R
  56,// S
  65,// T
  74,// U
  83,// V
  21,// W
  3, // X
  12,// Y
  30,// Z
};

int isValid(char* d) {
  int cs = map[d[0]-'A'];
  for (int i=1; i<9 i="" p="">    cs += (d[i] - '0') * (9-i);
  }
  cs += (d[9] - '0');
  return cs%10 == 0;
}

int main ()
{
  char id[20];
  while (scanf("%s", id) == 1) {
    printf ("%s\n", isValid(id)?"real":"fake");
  }
  return 0;
}

a017: 五則運算

a017: 五則運算


// 底下這一行,是因為要用 getline(), 這個是 c++ 才有的,或是要告訴 gcc 說,這個是 gnu 額外提供給 c 的
#define _GNU_SOURCE
#include

char *buf;
char *express;

// peek() 不移動字元位置,只傳回指標目前所指的字元
char peek() {
    while (*express == ' ') ++express; // 一律略過空白字元
    return *express;
}

// 因為 peek() 會略過空白字元,這邊直接傳回指標所指的字元
char get() { return *(express++); }

// 把數字傳回去,因為數字是連續的,所以....
int number() {
    int result = get() - '0';
    while (peek() >= '0' && peek() <= '9') result = 10*result + (get() - '0');
    return result;
}

// factor() 可以看成『分解成 + - 的『項』,小括號內的話,視為一項
int expression(); // 要遞迴呼叫,所以得先定義方法
int factor() {
    if (peek() >= '0' && peek() <= '9') return number();
    else if (peek() == '(') { // 遇上括號,則再遞回呼叫 expression()
        get(); // '('
        int result = expression();
        get(); // ')'
        return result;
    }
    else if (peek() == '-') {
        get();
        return -factor();
    }
    return 0; // error
}

// term() 則將各項運算結合起來, 主要是以 * / % 為主
int term() {
    int result = factor();
    char p = peek();
    while (p == '*' || p == '/' || p == '%') {
        p = get();
        if (p == '*') result *= factor();
        else if (p == '/') result /= factor();
        else result %= factor();
        p = peek();
    }
    return result;
}

int expression() {
    int result = term(); // 先取得第一項
    while (peek() == '+' || peek() == '-') { // 如果遇到 + - 號的話,則運算下一項的結合
        if (get() == '+') result += term();
        else result -= term();
    }
    return result;
}

int main ()
{
  size_t n;
  while (getline(&buf, &n, stdin) >= 0) {
    express = buf;
    int result = expression();
    printf ("%d\n", result);
  }
  return 0;
}

a016: 數獨(SUDOKU)

a016: 數獨(SUDOKU)


#include

int check(int* a) {
  // 1) 比對直線(橫+直)
  for (int k=0; k<9 k="" p="">    for (int i=0; i<9 i="" p="">      for (int j=i+1; j<9 j="" p="">        if (*(a+k*9+i) == *(a+k*9+j)) return 0; // 橫線
        if (*(a+i*9+k) == *(a+j*9+k)) return 0; // 直線
      }
    }
  }
  // 3) 比對3x3
  for (int m=0; m<3 m="" p="">    for (int n=0; n<3 n="" p="">      // 比對每個 3x3
      for (int j=0; j<9 j="" p="">        for (int i=0; i<9 i="" p="">          if (i != j && *(a+(m*3+j/3)*9+j%3+n*3) == *(a+(m*3+i/3)*9+i%3+n*3)) return 0;
        }
      }
    }
  }
  return 1;
}

int main ()
{
  int a[81];
  int *pa;
 
  while (!feof(stdin)) {
    pa = a;
    for (int i=0; i<9 i="" p="">      if (scanf ("%d %d %d %d %d %d %d %d %d", pa+0, pa+1, pa+2, pa+3, pa+4, pa+5, pa+6, pa+7, pa+8) != 9) return 0;
      pa += 9;
    }
    printf ("%s\n", check(a)?"yes":"no");
  }
  return 0;
}

a015: 矩陣的翻轉

a015: 矩陣的翻轉


#include

int main ()
{
  int m, n;
  int a[100][100];

  while (scanf ("%d %d", &m, &n) == 2) {
    for (int j=0; j      for (int i=0; i        scanf("%d", &a[j][i]);
    for (int j=0; j      for (int i=0; i        printf ("%d ", a[i][j]);
      printf ("%d\n", a[m-1][j]);
    }
  }
  return 0;
}

a013: 羅馬數字

a013: 羅馬數字


#include
#include
#include
#include

// 阿拉伯數字 --> 羅馬數字
int a2r(unsigned int val, char* res, size_t sz) {
  char *twas[] = {"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"};
  char *wans[] = {"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"};
  char *thos[] = {"", "M", "MM", "MMM", "Mv", "v", "vM", "vMM", "vMMM", "Mx"};
  char *huns[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
  char *tens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
  char *ones[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
  int   size[] = { 0,  1,    2,     3,    2,   1,    2,     3,      4,    2};

  if (val < 0) { strcpy(res, "UNKNOWN"); return 1; }
  if (val == 0) { strcpy(res, "ZERO"); return 1; }

  while (val >= 1000000) {
    if (sz-- < 1) return 0;
    *res++ = 'm';
    val -= 1000000;
  }

  // Add each of the correct elements, adjusting as we go.

  if (sz < size[val/100000]) return 0;
  sz -= size[val/100000];
  strcpy (res, twas[val/100000]); res += size[val/100000]; val = val % 100000;

  if (sz < size[val/10000]) return 0;
  sz -= size[val/10000];
  strcpy (res, wans[val/10000]); res += size[val/10000]; val = val % 10000;

  if (sz < size[val/1000]) return 0;
  sz -= size[val/1000];
  strcpy (res, thos[val/1000]); res += size[val/1000]; val = val % 1000;

  if (sz < size[val/100]) return 0;
  sz -= size[val/100];
  strcpy (res, huns[val/100]);  res += size[val/100];  val = val % 100;

  if (sz < size[val/10]) return 0;
  sz -= size[val/10];
  strcpy (res, tens[val/10]);   res += size[val/10];   val = val % 10;

  if (sz < size[val]) return 0;
  sz -= size[val];
  strcpy (res, ones[val]);      res += size[val];

  // Finish string off.
  if (sz < 1) return 0;
  *res = '\0';
  return 1;
}

int r2a_in_char(char r) {
  switch (r) {
    case 'I': return 1;
    case 'V': return 5;
    case 'X': return 10;
    case 'L': return 50;
    case 'C': return 100;
    case 'D': return 500;
    case 'M': return 1000;
    case 'v': return 5000;
    case 'x': return 10000;
    case 'l': return 50000;
    case 'c': return 100000;
    case 'd': return 500000;
    case 'm': return 1000000;
    default: return 0;
  }
}

int r2a(char *str) {
  int res = 0;
  int max = strlen(str);
  for (int i=0; i    // 從羅馬數字轉成阿拉伯數字
    int s1 = r2a_in_char(str[i]);
 
    if (i+1 < max) {
      // 往後看,將下一個字元從羅馬數字轉成阿拉伯數字
      int s2 = r2a_in_char(str[i+1]);
 
      // 比對前後文....
      if (s1 >= s2) {  // 前面大於等於後面,表示加法,直接加起來
        res = res + s1;
      } else {  // 前面小於後面,表示減法: 加後面減前面
        res = res + s2 - s1;
        i++; // i++ 之後,跳過下一符號
      }
    } else { // 結束.....
      res = res + s1;
      i++;
    }
  }
  return res;
}

int main ()
{
  int n, a, b;
  char r1[100], r2[100];
  char res[100];

  while (scanf ("%s %s", r1, r2) == 2) {
    a = r2a(r1);
    b = r2a(r2);
    a2r(a>b?a-b:b-a, res, 100);
    printf ("%s\n", res);
  }
  return 0;
}

a010: 因數分解

a010: 因數分解


#include
#include

int main ()
{
  int n, nn;

  while (scanf ("%d", &n) == 1) {
    int last = -1;
    int cnt=1;
    nn = sqrt(n);
    // 因為所有質因數只有2是偶數,先處理2
    while (!(n % 2)) {
      n >>= 1;
      if (last != 2) {
        printf ("2");
        last = 2;
        cnt = 1;
      } else cnt++;
    }
    if (cnt > 1) {
      printf ("^%d", cnt);
      cnt = 1;
    }
    for (int i = 3; i <= nn;) {
      if (n % i == 0) {
        n /= i;
        if (last != i) {
          if (cnt > 1) printf ("^%d * %d", cnt, i);
          else {
            if (last <= 0) printf ("%d", i);
            else printf (" * %d", i);
          }
          cnt = 1;
        } else cnt++;
        last = i;
      } else i += 2;
    }
    if (cnt > 1) {
      if (n > 1)
        printf ("^%d * %d\n", cnt, n);
      else
        printf ("^%d\n", cnt);
    } else if (n > 1) {
      if (last <= 0)
        printf ("%d\n", n);
      else
        printf (" * %d\n", n);
    } else puts("");
  }
  return 0;
}

上面的速度應該是比較快的,底下還有一個比較簡明的版本

#include
#include
#define push(n) fac[facn++] = (n)

int fac[1024];
int facn = 0;

void output() {
  int last = -1;
  int cnt = 0;
  for (int i=0; i 1) { // 有指數
        printf ("^%d * %d", cnt, fac[i]);
      } else {
        if (last <= 0) // 第一個
          printf ("%d", fac[i]);
        else // 不是第一個,沒有指數
          printf (" * %d", fac[i]);
      }
      cnt = 1;
    } else { cnt++; }
    last = fac[i];
  }
  if (cnt > 1) printf ("^%d\n", cnt); else printf ("\n");
}

int main ()
{
  int n, i, nn;

  while (scanf ("%d", &n) == 1) {
    facn = 0;
    nn = sqrt(n);
  
    // 因為所有質因數只有2是偶數,先處理2
    while (!(n % 2)) {
      n >>= 1;
      push(2);
    }
    for (i = 3; i <= nn; i+=2) {
      if (n % i == 0) {
        n /= i;
        push(i);
        i-=2;
      }
    }
    if (n > 1) push(n);
    output();
  }
  return 0;
}

a009: 解碼器

a009: 解碼器


#include                                                               
                                                                               
int main (int argc, char* argv[])                                             
{                                                                             
  int c;                                                                       
  while (EOF != (c = getchar())) {                                             
    if (c == '\n') printf ("\n");                                             
    else printf ("%c", (char)((c + 'C' - 'J')%255));                           
  }                                                                           
  return 0;                                                                   
}

a006: 一元二次方程式

a006: 一元二次方程式


#include                                                               
#include                                                                
                                                                               
int main (int argc, char* argv[])                                             
{                                                                             
  int a, b, c;                                                                 
                                                                               
  while (scanf ("%d %d %d", &a, &b, &c) == 3) {                               
    double r = (double)((b*b) - 4*(a*c));                                     
    if (r == 0.0) {                                                           
      printf ("Two same roots x=%.0lf\n", (double)(-b/(2.0*a)));               
    } else if (r > 0.0) {                                                     
      double s = sqrt(r);                                                     
      printf ("Two different roots x1=%.0lf , x2=%.0lf\n", (double)((-b+s)/(2.0*a)), (double)((-b-s)/(2.0*a)));                                               
    } else {                                                                   
      printf ("No real root\n");                                               
    }                                                                         
  }                                                                           
  return 0;                                                                   

a005: Eva 的回家作業

a005: Eva 的回家作業


#include                                                               
                                                                               
int main (int argc, char* argv[])                                             
{                                                                             
  int n, a[4], r;                                                             
                                                                               
  scanf ("%d", &n);                                                           
  for (int i=0; i    scanf ("%d %d %d %d", a, a+1, a+2, a+3);                                   
    if ((a[3] - a[0]) == (3*(a[1] - a[0]))) r = a[3]+a[3]-a[2];               
    else r = a[3]*a[3]/a[2];                                                   
    printf ("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], r);                   
  }                                                                           
  return 0;                                                                   

a004: 文文的求婚

a004: 文文的求婚


#include                                                               
                                                                                
int main (int argc, char* argv[])                                               
{                                                                               
  int a;                                                                        
  char m[2][10] = { "平", "閏" };                                               
  while (scanf ("%d", &a) == 1) {                                               
    printf ("%s年\n", m[!(a%400) || ((a%100) && !(a%4))]);                      
  }                                                                             
  return 0;                                                                     

}   

a003: 兩光法師占卜術

a003: 兩光法師占卜術


#include                                                               
                                                                               
int main (int argc, char* argv[])                                             
{                                                                             
  int a, b;                                                                   
  char m[3][10] = { "普通", "吉", "大吉" };                                   
  while (scanf ("%d %d", &a, &b) == 2) {                                       
    printf ("%s\n", m[(a*2+b)%3]);                                             
  }                                                                           
  return 0;                                                                   
}

zj-a002 簡易加法

zj-a002 簡易加法


#include                                                               
int main (int argc, char* argv[])                                             
{                                                                             
  int a, b;                                                                   
                                                                               
  while (scanf ("%d %d", &a, &b) == 2) {                                       
    printf ("%d\n", a+b);                                                     
  }                                                                           
  return 0;                                                                   
}

zj-a001 哈囉



zj-a001 哈囉
#include                                                               
int main (int argc, char* argv[])                                             
{                                                                             
  char name[1024];                                                           
                                                                             
  while (scanf ("%s", name) == 1) {                                           
    printf ("hello, %s\n", name);                                             
  }                                                                           
  return 0;                                                                   
}

2018/02/08

Android Proguard 範例

底下是我在某支程式中使用的範例,如果遇到一堆警告的話,通常是透過 -dontwarn 來解決,請見最後幾條。另外一種情況,最常見的解決方法就是用 -keep 來解決,請見前面幾條:

-dontusemixedcaseclassnames-dontskipnonpubliclibraryclasses-verbose-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*


-keep public class * extends android.**
-keep public class * extends java.**
-keep public class com.android.vending.licensing.ILicensingService
-keep public class com.google.**

-keepclasseswithmembernames class * {
 native ;}

-keep public class * extends android.view.View {
 public (android.content.Context); public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); public void set*(...);}

-keepclasseswithmembers class * {
 public (android.content.Context, android.util.AttributeSet);}

-keepclasseswithmembers class * {
 public (android.content.Context, android.util.AttributeSet, int);}

-keepclassmembers class * extends android.app.Activity {
 public void *(android.view.View);}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations-keepclassmembers enum * {
 public static **[] values(); public static ** valueOf(java.lang.String);}

-keep class * implements android.os.Parcelable {
 public static final android.os.Parcelable$Creator *;}

-keepclassmembers class **.R$* {
 public static ;}

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }
-dontwarn android.support.**
-dontwarn com.google.**
-dontwarn com.squareup.**

2018/01/05

續-快速產生特定大小的檔案 using dd fast create specified size file

寫過一篇

快速產生特定大小的檔案 using dd fast create specified size file


事實上我再做了個實驗,發現那篇有誤,我是指,還有更快的方法,就是直接 resize file 的方式:

dd bs=1048576 seek=4096 of=data.img count=0
前面 bs = 1M, seek 4K, 馬上就會得到 4G file data.img