2014年10月29日星期三

批次更改檔名 in Linux

因為先前寫UVa時,檔案名稱有時會花心思改,有時就直接把題目名稱加上.cpp就貼上了
導致現在有不同的格式出現

  

現在要處理的事情很簡單

1. 去除空白
2. 將底線 ( _ ) 換成dash ( - )

經過一番查詢,終於發現最簡單的方法 - rename指令
它是基於 Perl 底下發展出來的




NAME
       rename - renames multiple files

SYNOPSIS
       rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]

DESCRIPTION
       "rename" renames the filenames supplied according to the rule specified
       as the first argument.  The perlexpr argument is a Perl expression
       which is expected to modify the $_ string in Perl for at least some of
       the filenames specified.  If a given filename is not modified by the
       expression, it will not be renamed.  If no filenames are given on the
       command line, filenames will be read via standard input.

       For example, to rename all files matching "*.bak" to strip the
       extension, you might say

               rename 's/\.bak$//' *.bak

       To translate uppercase names to lower, you'd use

               rename 'y/A-Z/a-z/' *


重點來了,因為它是用 Perl expression,要稍微了解一下它的方式
不過指令本身的格式很簡單:

     rename 's/要改的部份/要變成的部份/' 目的檔案

所以操作的方式為

    rename 's/ //' *
    rename 's/_/-/' *

這樣就可以了

踏入Linux殿堂


距上次把Ubuntu裝在電腦裡頭,也有至少四五年的時間了

電腦也從原本的桌機換成現在使用的 Lenovo X201

據眾多網友所述,X系列對Ubuntu的支持性不錯

再加上想重新溫習一下過去網管的技術和經驗

所以下載了 Ubuntu 14.10,弄了一張Live SD卡

用它快速地裝了起來



令人訝異地是,現在的發行版設計的真不錯

雖然有點不習慣,但至少程式運行的效率有顯著提昇

對硬體的支援也加強了

但還是比較習慣用Terminal + vim + gcc 來編寫程式

趕緊來試寫看看UVa吧


另外還有一款可以運行在Linux的遊戲 Teeworld

技巧不是很純熟,玩起來有點癟手癟腳的

不過真的挺有趣,有興趣的可以試試看

https://www.teeworlds.com/

2014年10月28日星期二

[UVa] 10474 - Where is the Marble?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;


int main(){

  //freopen("input.txt","r",stdin);
  int N,Q;
  int n[10000],q[10000];
  int cases=0;
  while(1){
    scanf("%d %d", &N, &Q);
    if(N==0 && Q==0)break;
    printf("CASE# %d:\n",++cases);
    memset(n,0,sizeof(n));
    memset(q,0,sizeof(q));
    for(int i=0;i<N;i++)scanf("%d",&n[i]);
    for(int i=0;i<Q;i++)scanf("%d",&q[i]);
    //for(int i=0;i<N;i++)printf("%d ",n[i]); 
    for(int i=0;i<N;i++){
      for(int j=i+1;j<N;j++){
        if(n[i]>n[j]){
          int tmp = n[i];
          n[i] = n[j];
          n[j] = tmp;
        }
      }
    }
    for(int i=0;i<Q;i++){
      for(int j=0;j<N;j++){
        if(n[j]==q[i]){
          printf("%d found at %d\n", q[i], j+1);
          break;
     }
        if(j==N-1 && n[j]!=q[i])printf("%d not found\n", q[i]);
        //break;
      }
    }
    //for(int i=0;i<N;i++)printf("%d ",n[i]); printf("\n");
    //for(int i=0;i<Q;i++)printf("%d ",q[i]); printf("\n");
   
  } 
  return 0;
}

2014年10月20日星期一

[UVa] 10420 - List of Conquests


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

int main(){
  //freopen("input.txt","r",stdin);
  char a[76]; 
  string countries[3000];  // record countries
  string buffer; //country to compare
  char tmp[100];
  int country_count[3000]; // count the girls each country
  memset(country_count,0,sizeof(country_count));
  
  int n;
  scanf("%d",&n);
  getchar();
  for(int i=0;i<n;i++){
    fgets(a,sizeof(a),stdin); //讀取一整行
    for(int j=0;j<76;j++){  
      if(a[j]!=' ')tmp[j]=a[j];  //在第一個空白出現之前,將字元存入tmp
      else break; //讀取到空白就跳出,如此僅拿取前面的國家,後面名字不理會
    }
    countries[i] = tmp; // tmp 指定給 countries[i]
  }
  sort(countries,countries+n); //按字典排序
  
  int count=0;
  for(int i=0;i<n;i++){
    if(i==0){
      buffer = countries[i];  //一開始先將第一個國家存入暫存
    }
    if(buffer == countries[i]){ //如果接下來讀取的國家和暫存器相同
      country_count[count]++;  //計數器+1
    }
    
    if(buffer != countries[i] || i == n-1){  //如果讀取的國家和暫存不同,或是讀取到最後一個項目
      cout << buffer << " " << country_count[count] << '\n'; //輸出暫存器國家,和該國家的計數
      count++; //切換到下一個國家的計數
      buffer = countries[i];  //切換到下一個國家,存入暫存
      country_count[count]++; //新國家的計數器+1
    }
  }  
  
  
  return 0;
}

[UVa] 340 - Master-Mind Hints

這和以前常玩的 _A_B 猜數字一樣
只不過可以重複猜同樣的數字
所以檢查時也要特別注意
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <cstdio>
//#include <cstring>
//#include <iostream>
using namespace std;
int main(){
  freopen("input.txt","r",stdin);
  int n;
  int game_num = 1;
  while(scanf("%d",&n)!=EOF){
    if(n==0)break;
 
    printf("Game %d:\n", game_num++); // print game number
 
    int s[n]; memset(s,0,sizeof(s)); //Secret code
    for(int i=0;i<n;i++)scanf("%d",&s[i]);  //Input secret code
 
 
 int g[n]; memset(g,0,sizeof(g)); //Guess code
 while(1){
   
   int check[n];  //檢查用的陣列,和s陣列相同
   for(int i=0;i<n;i++)check[i]=s[i]; //檢查用的陣列
 
   for(int i=0;i<n;i++)scanf("%d",&g[i]); //Input guess code
   if(g[0]==0)break; 
   
   int a=0,b=0; // hint a and b, (a,b)
   
   for(int i=0;i<n;i++) 
     if(g[i]==check[i]){
    a++;
    check[i]=0;
    g[i]=0;
     }
   for(int i=0;i<n;i++)
     for(int j=0;j<n;j++){
    if(g[i]==check[j] && g[i]!=0){
      b++;
   check[j]=0;
   g[i]=0;
    }
  }
   printf("    (%d,%d)\n",a,b);
 }
 
 //for(int i=0;i<n;i++)
    //  printf("%d ",s[i]);
 //printf("\n");
  }
  
  return 0;
}  

2014年10月6日星期一

[UVa] 10494 - If We Were a Child Again


這次直接使用大數除法來運算


1. 取得a及b的位數數目len_a、len_b
2. 將乘數b乘上10的 (len_a - len_b) 次方,也就是前移(len_a-len_b)位
3. 由i=0開始將a和b*i比較,找出滿足b*i≦A<B*(i+1)的i
4. 商的 len_a-len_b+1位 ( 即 c[len_a-len_ b ) 就是i, a = a - b*i ,b=b/10
5. 重複直到 len_a - len_b==0


//Big number : http://www.csie.ntnu.edu.tw/~u91029/BigNumber.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 10000

using namespace std;

int len_a,len_b;  //a和b的長度

void print(int a[maxn]){
  int i=maxn-1;       // 要印的數字位置
  while(i>=0 && a[i]==0) i--; // 數字開頭的零都不印
  if(i<0)cout << '0';
  else while(i>=0) cout << a[i--]; 
}

// a > b  or  a < b
int compare(int a[maxn], int b[maxn]) 
{ 

  
  for (int i=maxn-1; i>=0; i--)    // 從高位數開始比,對應的位數相比較。
    if (a[i] != b[i] && a[i] > b[i]){       // 發現 a b 不一樣大,馬上回傳結果。
      return 1; // 1 = a>b
    }
    else if (a[i] != b[i] && a[i] < b[i]){
      return 2; // 2 = a<b
    }
    return false;       // 完全相等
}

// c = a + b;
void add(int a[maxn], int b[maxn], int c[maxn])
{
  for (int i=0; i<maxn; i++)   // 對應的位數相加
    c[i] = a[i] + b[i];
            
  for (int i=0; i<maxn-1; i++) // 一口氣進位
  {
    c[i+1] += c[i] / 10;    // 進位
    c[i] %= 10;             // 進位後餘下的數
  }
}

// c = a - b
void sub(int a[maxn], int b[maxn], int c[maxn])
{
  //code優化
  int max;
  if(len_a>=len_b)max=len_a;
  else max = len_b;
  
  for (int i=0; i<max; i++)   // 對應的位數相加
    c[i] = a[i] - b[i];
            
  for (int i=0; i<max-1; i++) // 一口氣補位
  {
    if(c[i]<0){
      c[i] += 10;
      c[i+1] --;             
    }
  }
}



// c = a * b;
void mul(int a[maxn], int b[maxn], int c[maxn])
{
  //code優化
  int max;
  if(len_a>=len_b)max=len_a;
  else max = len_b;
  
  for (int i=0; i<max; i++)
    c[i] = 0;
     
    for (int i=0; i<max; i++)
      for (int j=0; j<max; j++)
        if (i+j < max)
          c[i+j] += a[i] * b[j];
                    
    for (int i=0; i<max-1; i++) // 一口氣進位
    {
      c[i+1] += c[i] / 10;
      c[i] %= 10;
    }
}

// c = a / b
void div(int a[maxn], int b[maxn], int c[maxn])
{
    //code 優化
    int max=0;
    if(len_a>=len_b)max=len_a+1;
    else max = len_b+1;
    
    int  t[maxn]={0};
    int  t2[maxn]={0};
    int  b2[maxn]={0};
    int  b3[maxn]={0};
    
    int len_diff = len_a-len_b; //兩數字位數差 difference of length
    memset(t,0,sizeof(t));
    t[len_diff]=1; //t陣列的用意是,創造一個"...001000..."的陣列,好讓除數可以乘上
    
    while(len_diff >= 0){
        memset(b2,0,sizeof(b2));        
        mul(b,t,b2); //b2 = b * t
        
        for(int i=9;i>0;i--){  //商數由9→1
          memset(b3,0,sizeof(b3));
          for(int j=max-1;j>=0;j--){
            b3[j] = b2[j] * i; // b3 = b2 * i ,測試商數 
          } 
          for(int j=0;j<max;j++){
            while(b3[j]>=10){  //所有位數進位
              b3[j]-=10;
              b3[j+1]+=1;
            }
          }
          if(compare(a,b3)==1 || compare(a,b3)==0){ //若a>=b3
            c[len_diff]+=i; // 於len_diff的商數+1
            sub(a,b3,t2);   // t2 = a - b3 
            for(int j=0;j<max;j++)a[j]=t2[j];  //a = t2
            memset(t2,0,sizeof(t2));
          }

        }

        memset(t,0,sizeof(t));
        len_diff--; //位數往前一位
        if(len_diff>=0)t[len_diff]=1;
    }
    
}

void mod(int a[maxn], int b[maxn], int c[maxn])
{

    //code 優化
    int max=0;
    if(len_a>=len_b)max=len_a;
    else max = len_b;
    
    int  t[maxn]={0};
    int  t2[maxn]={0};
    int  b2[maxn]={0};
    int  b3[maxn]={0};

    int len_diff = len_a-len_b; //兩數字位數差
    t[len_diff]=1;

    while(len_diff>=0){
        memset(b2,0,sizeof(b2));        
        mul(b,t,b2);    
        for(int i=9;i>0;i--){
          memset(b3,0,sizeof(b3));
          for(int j=max-1;j>=0;j--){
            b3[j] = b2[j] * i;
            while(b3[j]>=10){
              b3[j]-=10;
              b3[j+1]+=1;
            }
          }
          
          if(compare(a,b3)==1 || compare(a,b3)==0){
            sub(a,b3,t2);
            for(int j=0;j<max;j++)a[j]=t2[j]; // a = t2
            for(int j=0;j<max;j++)c[j]=t2[j]; // c = t2
            memset(t2,0,sizeof(t2)); 
          }


        }
        memset(t,0,sizeof(t));
        len_diff--;
        if(len_diff>=0)t[len_diff]=1;
    }
}


char input_a[maxn]={'\0'};
char op,op1,op2,op3;
char input_b[maxn]={'\0'};
int a[maxn],b[maxn],result[maxn];

int main(){
  freopen("input.txt","r",stdin);
  while(scanf("%s%s%s",&input_a,&op2,&input_b)!=EOF){
    memset(a,'\0',sizeof(a));
    memset(b,'\0',sizeof(b));
      memset(result,'\0',sizeof(result));
    
    //printf("%s %c %s\n",input_a,op2,input_b);
    
    //轉換為倒轉數字陣列
    len_a = strlen(input_a);
    for(int i=0;i<len_a;i++){
      a[i]=input_a[len_a-i-1]-48;
    }
    len_b = strlen(input_b);
    for(int i=0;i<len_b;i++){
      b[i]=input_b[len_b-i-1]-48;
    }
      
      if(op2=='/'){
        if(compare(a,b)==2)printf("0"); //若b>a,則為0
        else if(len_b==1 && b[0]==0)break;
        else {
          div(a,b,result);
          print(result);
        }
      }
      if(op2=='%'){
        if(compare(a,b)==2)print(a); //若b>a,餘數則為a
        else {
          mod(a,b,result);
          print(result);
        }
      }
      printf("\n");

  }
  
  return 0;  
} 







2014年10月2日星期四

[UVa] 748 - Exponentiation

比較難處理的一題
這邊要將前面和後面的0通通去掉
在 print 函數裡下了不少工夫
大數運算參考 演算法筆記  - Big Number
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 1000
using namespace std;
// print

int dot;
void print(int a[maxn]){
  int i=maxn-1;       // 要印的數字位置
  int stop=0; 
  int dot_appear=0;
  while(i>=0 && a[i]=='\0' && i+1>dot) i--; // 數字開頭的零都不印
  if(i<0)cout << '0';
  else while(i>=0 && stop!=1) { //stop不等於1時,持續輸出數字
 if(i+1==dot){
   cout << '.';
   dot_appear=1;
 }
 if(dot_appear==1){ //從輸出小數點後,針對後面的數字做檢查
   stop=1; //若後面皆為0,則stop=1
   for(int j=i;j>=0;j--){
     if(a[j]!=0){ //若後面有非0者,stop=0
       stop=0; break;
     }
   }
 }
 if(stop!=1)cout << a[i]; 
 i--;
  }
}
 // c = a * b;
void mul(int a[maxn], int b[maxn], int c[maxn]){
  for (int i=0; i<maxn; i++)
    c[i] = 0;
     
    for (int i=0; i<maxn; i++)
      for (int j=0; j<maxn; j++)
        if (i+j < maxn)
          c[i+j] += a[i] * b[j];
                    
    for (int i=0; i<maxn-1; i++) // 一口氣進位
    {
      c[i+1] += c[i] / 10;
      c[i] %= 10;
    }
}

char input[maxn]; 
int a[maxn],b[maxn],result[maxn];

int main(){
  freopen("input.txt","r",stdin);
  for(int i=0;i<maxn;i++)a[i]='\0';
  for(int i=0;i<maxn;i++)b[i]='\0';
  for(int i=0;i<maxn;i++)result[i]='\0';
  
  while(scanf("%s",&input)!=EOF){
    
 //紀錄小數點後有幾位
 dot=0;
 int len = strlen(input);
 for(int i=len-1;i>0;i--){
   if(input[i]=='.')break;
   dot++;
 }
 
 //change input into integer array
    for(int i=0;i<len;i++){
   a[i]=input[len-i-1]-48;
 }
 
 //將小數點去掉
 for(int i=dot;i<len;i++){
   a[i]=a[i+1];
   a[i+1]=0;
 }
 
 
 for(int i=0;i<maxn;i++)b[i]=a[i]; //將a複製給b
 
 int n;
 scanf("%d",&n);
 dot *= n; //乘幾次,小數點後位數就加倍幾次
 n--;
 while(n--){
   mul(a,b,result); //每次的b乘給a
   for(int i=0;i<maxn;i++)b[i]=result[i]; //將result複製給b
 }
 
 /*
 for(int i=0;i<maxn;i++){
   if(result[i]==0)printf("%d",result[i]);
   else if(result[i]=='\0'); 
   else printf("%d",result[i]);
 }
 */
 //printf("\n");
    print(result);
    printf("\n");
 
  }
  
  return 0;  
} 

2014年10月1日星期三

[UVa] 465 - Overflow

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <cstring>
#include <iostream>

#define maxn 1000 
// E.X. max of int is 2147483647


using namespace std;

// print
void print(int a[maxn]){
  int i=maxn-1;       // 要印的數字位置
  while(i>=0 && a[i]==0) i--; // 數字開頭的零都不印
  if(i<0)cout << '0';
  else while(i>=0) cout << a[i--]; 
}

// a > b  or  a < b
int compare(int a[maxn], int b[maxn]) 
{
  for (int i=maxn-1; i>=0; i--)    // 從高位數開始比,對應的位數相比較。
    if (a[i] != b[i] && a[i] > b[i]){       // 發現 a b 不一樣大,馬上回傳結果。
   return 1; // 1 = a>b
 }
 else if (a[i] != b[i] && a[i] < b[i]){
   return 2; // 2 = a<b
 }
    return false;       // 完全相等
}

// c = a + b;
void add(int a[maxn], int b[maxn], int c[maxn])
{
  for (int i=0; i<maxn; i++)   // 對應的位數相加
    c[i] = a[i] + b[i];
            
  for (int i=0; i<maxn-1; i++) // 一口氣進位
  {
    c[i+1] += c[i] / 10;    // 進位
    c[i] %= 10;             // 進位後餘下的數
  }
}

// c = a * b;
void mul(int a[maxn], int b[maxn], int c[maxn])
{
  for (int i=0; i<maxn; i++)
    c[i] = 0;
     
    for (int i=0; i<maxn; i++)
      for (int j=0; j<maxn; j++)
        if (i+j < maxn)
          c[i+j] += a[i] * b[j];
                    
    for (int i=0; i<maxn-1; i++) // 一口氣進位
    {
      c[i+1] += c[i] / 10;
      c[i] %= 10;
    }
}


char max_int[maxn] = "2147483647";
char input_a[maxn]={'\0'};
char op1,op2,op3;
char input_b[maxn]={'\0'};
int a[maxn],b[maxn],intmax[maxn],result[maxn];

int main(){
  for(int i=0;i<maxn;i++)a[i]=0;
  for(int i=0;i<maxn;i++)b[i]=0;

  while(scanf("%s",&input_a)!=EOF){
      scanf("%c%c%c",&op1,&op2,&op3);
   scanf("%s",&input_b);
   printf("%s %c %s\n",input_a,op2,input_b);
   
   
   //change input into integer array
   int len = strlen(input_a);
      for(int i=0;i<len;i++){
     a[i]=input_a[len-i-1]-48;
   }
   
   len = strlen(input_b);
   for(int i=0;i<len;i++){
     b[i]=input_b[len-i-1]-48; 
   }
   
   len = strlen(max_int);
      for(int i=0;i<len;i++){
     intmax[i]=max_int[len-i-1]-48; 
   }

   
   
   int cmp_a = compare(a,intmax);
   if(cmp_a==1)printf("first number too big\n");
 
   int cmp_b = compare(b,intmax);
   if(cmp_b==1)printf("second number too big\n");

   if(op2=='+')add(a,b,result);
   if(op2=='*')mul(a,b,result);   
   
   int cmp_result = compare(result,intmax);
   if(cmp_result==1)printf("result too big\n");
   
   memset(a,0,sizeof(a));
   memset(b,0,sizeof(b));
   memset(result,0,sizeof(result));
  }

  return 0;  
}