(learn&think)

不浮躁,不自傲,学习,思考,总结

Programming Pearls: Column3

| Comments

Book notes

主旨是:don’t wirte a big program when a little one will do.

一些原则:

  1. 重构重复的代码到数组。
  2. 封装复杂的结构。
  3. 尽可能使用高级工具。
  4. 让数据来构建程序。

Problems

1

  1. 建立一张税收表格,包括 1.这个一行数据范围的最低收入; 2.税收的基本费用; 和 3.税收比率。
  2. 用给定税收,二分搜索所处范围,也就是表格的哪一栏。用公式算出税收。

3

编写标语函数,输入一个大写字母,输出一个字符数组,该字符数组用字符图形方式描绘该字母

  1. 用一个定义的模板语言为每个字母定义标语的格式,存入一个 table 中;
  2. 写一个对这个自定义模板语言的解析程序,把它解析成打印标语;
  3. 输入一个单词,直接读取 table 相应的模板格式,用解析程序解析。

如字母 I 如下,可以把它编码成:

3 lines 9 X
6 lines 3 blank 3 X 3 blank
3 lines 9 X

或更简化:

3 9 X
6 3 b 3 x 3 b
3 9 x
x  x  x  x  x  x  x  x  x
x  x  x  x  x  x  x  x  x
x  x  x  x  x  x  x  x  x
         x  x  x         
         x  x  x         
         x  x  x         
         x  x  x         
         x  x  x         
         x  x  x         
x  x  x  x  x  x  x  x  x
x  x  x  x  x  x  x  x  x
x  x  x  x  x  x  x  x  x

4

#include <cstdio>
#include <vector>
using std::vector;

struct Date {
  Date(int year_in, int month_in, int day_in) {
    year = year_in;
    month = month_in;
    day = day_in;
  }
  int year;
  int month;
  int day;
};

const int kMonthDays[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int KDaysOfWeek = 7;
enum YearDays {
  kNormYearDays = 365,
  kLeapYearDays = 366,
};

bool IsLeapYear(const int &year) {
  if ((year % 400 == 0) ||
      (((year % 4) == 0) && (year % 100) != 0)) {
    return true;
  } else {
    return false;
  }
}

int MonthDaysOfYear(int year, int month) {
  int days = kMonthDays[month];
  if (month == 2 && IsLeapYear(year)) {
    days++;
  }
  return days;
}

int DaysOfYear(const Date &date) {
  int days = 0;
  days += date.day;
  for (int i = 1; i < date.month; ++i) {
    days += MonthDaysOfYear(date.year, i);
  }
  return days;
}

int DaysBetween(const Date &date_pre, const Date &date_next) {
  int days = 0;
  for (int year_ = date_pre.year; year_ < date_next.year; ++year_) {
    days += (IsLeapYear(year_) ? kLeapYearDays : kNormYearDays);
  }
  days += DaysOfYear(date_next);
  days -= DaysOfYear(date_pre);
  return days;
}

void PrintCalendar(const vector<vector<int> > &calendar) {
  printf("Sun Mon Tue Wed Thu Fri Sat\n");
  int i;
  for (i = 0; i < KDaysOfWeek - calendar[0].size(); ++i) {
    printf("    ");
  }
  for (i = 0; i < calendar.size(); ++i) {
    for (int j = 0; j < calendar[i].size(); ++j) {
      printf("%-4d", calendar[i][j]);
    }
    printf("\n");
  }
}

int DayOfWeek(const Date &date) {
  const Date kFirstDate(1900, 1, 1);  // Mon
  return (DaysBetween(kFirstDate, date) % 7 + 1);
}

void CalendarOfMonth(int year, int month, vector<vector<int> > *calendar) {
  Date first_of_month(year, month, 1);
  int day_of_week = DayOfWeek(first_of_month);
  vector<int> temp;
  for (int i = 0; i < MonthDaysOfYear(year, month); ++i) {
    temp.push_back(i);
    if ((day_of_week + i) % KDaysOfWeek == 6) {
      calendar->push_back(temp);
      temp.clear();
    }
  }
  printf("Year:%d Month:%d\n", year, month);
  PrintCalendar(*calendar);
}

5

查找后缀连字符的连接。

const char *kHyphWords[] = {"et-ic", "al-is-tic", "s-tic", "p-tic", "-lyt-ic",
                      "ot-ic", "an-tic", "n-tic", "c-tic", "at-ic",
                      "h-nic", "n-ic", "m-ic", "l-lic", "b-lic",
                      "-clic", "l-ic", "h-ic", "f-ic", "d-ic",
                      "-bic", "a-ic", "-mac", "i-ac"};

static vector<string> *reverse_hyphs = NULL;

void ReverseHypenation(const char *word, char *reverse_word) {
  const char kHypen = '-';
  int len = strlen(word) - 1;
  int i, j;
  for (i = 0, j = 0; i <= len; ++i) {
    if (word[len - i] == kHypen)
      continue;
    reverse_word[j++] = word[len - i];
  }
  reverse_word[j] = '\0';
}

void RerverseWord(const string &word, string *reverse_word) {
  *reverse_word = word;
  reverse(reverse_word->begin(), reverse_word->end());
}

void PreProcessHyphenation() {
  if (reverse_hyphs != NULL) {
    return;
  } else {
    reverse_hyphs = new vector<string>();
    int n = sizeof(kHyphWords) / sizeof(kHyphWords[0]);
    for (int i = 0; i < n; ++i) {
      const int kMaxLen = 10;
      char reverse_word[kMaxLen];
      ReverseHypenation(kHyphWords[i], reverse_word);
      reverse_hyphs->push_back(string(reverse_word));
    }
  }
}

bool IsBeginWith(const string &word, const string &begin_letter) {
  if (word.size() < begin_letter.size()) {
    return false;
  }
  for (int i = 0; i < begin_letter.size(); ++i) {
    if (begin_letter[i] != word[i]) {
      return false;
    }
  }
  return true;
}

string FindHyphenation(const string &word) {
  PreProcessHyphenation();
  string reverse_word;
  RerverseWord(word, &reverse_word);
  for (int i = 0; i < reverse_hyphs->size(); ++i) {
    if (IsBeginWith(reverse_word, reverse_hyphs->at(i))) {
      return string(kHyphWords[i]);
    }
  }
  return "";
}

Comments