顯示具有 Java 標籤的文章。 顯示所有文章
顯示具有 Java 標籤的文章。 顯示所有文章

LeetCode OJ: 125. Valid Palindrome 迴文判斷

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

題目連結 https://leetcode.com/problems/valid-palindrome/

此題和a022: 迴文a038: 數字翻轉LeetCode OJ: 9. Palindrome Number 迴文數字類似。但本次要用Java String 的函數 reverse()來解。先將非英文字母與數字給刪除,並轉成小寫,之後就可以呼叫 reverse()做翻轉為 rev 字串,並和原字串 actual 比較是否相同。

程式碼:
1
2
3
4
5
6
7
public class Solution {
    public boolean isPalindrome(String s) {
        String actual = s.replaceAll("[^A-Za-z0-9]", "").toLowerCase();
        String rev = new StringBuffer(actual).reverse().toString();
        return actual.equals(rev);
    }
}

打造自己的APCS實作題系統環境

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

底下文件是參考APCS官網所提供的系統環境資訊而建立出來的虛擬環境,用的 Lubuntu 版本是Lubuntu Desktop 18.04 (32-bit)

文件下載處:APCS_Lubuntu環境建立

各種程式語言從檔案讀取一行文字的方法

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

在程式語言裡,常常會需要讀取一行文字。那麼在各式各樣程式語言中的程式碼又會是何種樣子呢?底下分別列出筆者知道的程式語言之寫法。

C語言


C++語言


Java語言


Python語言


C#語言

電腦遊戲設計入門

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

本部落格的幾篇文章:
說明了一些開發環境的建立,也介紹了一些小遊戲的做法。但,設計電腦遊戲一定要學程式設計嗎?例如 開源跨平台遊戲開發工具介紹:GDevelop 文中提到的 GDevelop 以及 遊戲程式開發工具與網站 ( Tools and their website for game programming ) 所提到的 Clickteam FusionRPG Maker,這三款軟體皆可不需撰寫程式碼,就可以設計遊戲囉。

除了這三款軟體之外,還有沒有其他的工具呢?當然有(不然要這篇文章做什麼呢!?)。此類軟體有免費與付費的,底下就分為這兩類來介紹。

須付費電腦遊戲設計軟體:
Game Maker https://www.yoyogames.com/gamemaker
Game Maker 最初推出的時候,有免費的版本,現在有30天試用的版本。提供拖拉(drag and drop)功能,讓使用者只要熟悉幾個指令就可以開發遊戲。除了拖拉方式外,也提供腳本語言GameMaker Language給開發者撰寫程式碼。

Construct 3 https://www.construct.net/en
除了有 Construct2 的功能外,增加了底下功能:支援Mac 和 Linux系統、多國語言、第三方工具的擴充。Construct3的使用方式可參考此連結:Construct3教學文章

GameSalad https://gamesalad.com/
GameSalad這套軟體一樣有視覺式的編輯畫面,操作方式像Flash與Dreamweaver,開發者只需要把遊戲物件放到當位置,並設定相關的物理原則,即可設計出簡單的2D遊戲囉。

免費電腦遊戲設計軟體:
Stencyl http://www.stencyl.com/
Stencyl官網標榜「Create Amazing Games Without Code」,不會寫程式也可製作出HTML5與Flash遊戲。也是透過拖拉的方式來進行遊戲的製作。

Construct 2 https://www.scirra.com/construct2以HTML5為城市語言的2D遊戲開發工具,透過視覺化的界面與拖拉動作,即可讓沒有程式設計基礎的人來完成一個遊戲。Construct2的使用方式可參考此連結:Construct2教學文章

題外話:免費的遊戲設計軟體還是會有一些功能限制,例如無法將開發好的遊戲發布到App商店上去賣等。

APCS解題技巧

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

底下分享筆者在解APCS實作題相關題目(如高中生解題系統LeetCodeUVa Online JudgeHackerRank等)以及APCS觀念題所用到的技巧。

一、看懂題目
這一點是最重要的,因為看不懂APCS的題目時,也就等於準備交白卷啦。但請在仔細想想,若看不懂題目時,要怎麼辦呢?這部分要怎麼讓自己增加看懂題目的能力呢?
請嘗試看很多不同的題目並看懂,但先不要解題。
請嘗試看很多不同的題目並看懂,但先不要解題。
請嘗試看很多不同的題目並看懂,但先不要解題。
為什麼要這樣子做呢?因為我們不知道APCS的題目類型會是怎麼樣,讓自己熟悉不同類型的題目時,就可以很快地知道題目的重點在那兒。底下分別以幾個例子說明APCS觀念題與實做題的一些題目類型。

觀念題部份(圖取自APCS官方提供的歷屆試題):

以上幾題主要是考遞迴函式的觀念,也包含函式迴圈判斷陣列等觀念。

實做題部份(圖取自APCS官方提供的歷屆試題):


這部份的每一次考試的試題會有四題,題目幾乎都是由易入難(第一題最簡單,第四題最困難),且每題都會說明評分方式,因此會有部份給分的情況,所以作答時應依自己最容易取得分數的部份開始做起

二、分析題目
遇到不熟悉的觀念題題目時,可以先用紙筆將程式的每一行程式碼執行結果記錄下來,這樣子可以了解程式碼的運算結果是什麼,接著再來分析這些結果有什麼規律來找出規則。實作題部份都會說明題目以及範例說明,基本上也是得看懂題目才能想出解法。根據官方所提供的實作題:2017-10-28_實作題_試題下載2017-03-04_實作題_試題下載2016-10-29_實作題_試題下載2016-03-05_實作題_試題下載。可以了解到,考題都是偏向要想出演算法來解題,所以除了程式語言的語法觀念外,還需熟悉一些基礎演算法,例如排序搜尋堆疊佇列等觀念。主流的程式語言通常會有這些常見演算法的函式可用,這部份在後面說明。

三、善用工具
朋友們有看過本部落格的「APCS 解題:特殊編碼」這篇文章嗎?這篇文章用了字典的觀念,並以C++、Java、Python三種程式語言來實作。疑!沒有用C程式語言來實作耶!這是因為C語言內建函式工具沒有支援hash table的資料結構。

這部份會用幾個例子來說明善用APCS所指定的程式語言:C、C++、Java、Python的工具函式會有多便利,先以最常見的排序與搜尋演算法當例子。

排序
C語言有內建的qsort。C++除了可以使用qsort外,還可以使用STL的sort。Java有Arrays.sortCollections.sort。Python則有list.sort與sorted可用。

搜尋
最常見的搜尋為線性搜尋二分搜尋。線性搜尋的演算容易實作出來,所以直接說明二分搜尋的部份。C語言有內建的bsearch。C++除了可以使用bsearch外,還可以使用STL的binary_search。Java有Arrays.binarySearchCollections.binarySearch。Python則有bisect模組可用。

String字串相關函式
熟悉一些字串操作的函式對實作是有幫助的,此處列出這四種程式語言相關函式之連結:常見的C語言字串函式常見的C++語言字串函式常見的Java語言字串函式常見的Python語言字串函式

大數運算
電腦的數值表示方式有上限值,比如整數最大值可能為232 - 1等於4,294,967,295 。要計算12345678901234567890 + 98765432109876543210 時,通常就會發生overflow了。但在Java語言中,可以使用BigInteger來解題,本部落格的文章:「高中生程式解題系統:大數運算」就是使用BigInteger來解題。

函式庫
以函式庫的豐富性來說,C語言的內建函式庫是最少的。這樣來說,對選用C語言實作的考生們不就吃虧大了?這也別擔心太多,根據筆者目前所看到的實作題題庫來說,出題方向很少會需要使用內建函式庫來解題的不過多了解程式語言的內建函式庫,可讓自己在解題有更多的選擇喔!因為APCS實作題是考解題方法,偏重演算法與資料結構,在這兩個主題上,C++可以學習Standard Template LibraryJava語言本身就有常見的資料結構可以使用了,用Java實作演算法也會比C與C++還容易一些;而Python也有內建資料結構可用,以及豐富的函式庫喔,這也是為什麼熟悉Python語法與內建函式庫的人,大多會選用Python來實作。

以上的資訊提供給要考APCS的考生們,希望對考生們在解題時有些幫助。

APCS 實作題 10610 第1題邏輯運算子參考解法

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

題目說明請看高中生解題系統上的「c461: apcs 邏輯運算子 (Logic Operators)」或是底下圖片。


此題考C語言的「非零為True之觀念」,解法很單純,將非零的數值轉為True,以及邏輯運算就可以了。筆者用四種版本的語言來實作。

C 語言:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <stdbool.h>

int main() {
  int a, b, c;

  while(scanf("%d %d %d", &a, &b, &c) == 3)
  {
    // 非零轉為True
    if(a > 0) a = true;
    if(b > 0) b = true;
    c == 1 ? true : false;

    bool hasAns = false;
    
    // 邏輯運算結果
    if( (a & b) == c )
    {
      printf("AND\n");
      hasAns = true;
    
    }
    if( (a | b) == c )
    {
      printf("OR\n");
      hasAns = true;
    }

    if( (a ^ b) == c )
    {
      printf("XOR\n");
      hasAns = true;
    }

    if( hasAns == false )
      printf("IMPOSSIBLE\n");
  }

  return 0;
}

C++語言:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <cstdbool>

using namespace std;

int main() {
  int a, b, c;
  while(cin >> a >> b >> c)
  {
    // 非零轉為True
    if(a > 0) a = true;
    if(b > 0) b = true;
    c == 1 ? true : false;

    bool hasAns = false;
    // 邏輯運算結果
    if( (a & b) == c )
    {
      cout << "AND" << endl;
      hasAns = 1;
    }

    if( (a | b) == c )
    {
      cout << "OR" << endl;
      hasAns = 1;
    }

    if( (a ^ b) == c )
    {
      cout << "XOR" << endl;
      hasAns = 1;
    }

    if( hasAns == 0 )
      cout << "IMPOSSIBLE" << endl;
  }

  return 0;
}

Java語言:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.util.*;

class Main {
  public static void main(String[] args) {
    Scanner cin = new Scanner(System.in);
  int a, b, c;
    boolean aFlag, bFlag, cFlag;

  while (cin.hasNext()) {
      a = cin.nextInt();
      b = cin.nextInt();
      c = cin.nextInt();

      // 非零轉為True
      aFlag = a > 0 ? true: false;
      bFlag = b > 0 ? true: false;
      cFlag = c > 0 ? true: false;
      
      boolean hasAns = false;
      // 邏輯運算結果
      if( (aFlag & bFlag) == cFlag )
      {
        System.out.println("AND");
        hasAns = true;
      }

      if( (aFlag | bFlag) == cFlag )
      {
        System.out.println("OR");
        hasAns = true;
      }

      if( (aFlag ^ bFlag) == cFlag )
      {
        System.out.println("XOR");
        hasAns = true;
      }

      if( hasAns == false )
        System.out.println("IMPOSSIBLE");
      }
  }
}

Python語言:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import sys

for num in sys.stdin:
    a,b,c = list(map(int, num.split()))
    
    #非零轉為True
    if( a > 0):
      a = True
    else:
      a = False;
  
    if( b > 0):
      b = True
    else:
      b = False;
  
    if( c > 0):
      c = True
    else:
      c = False
  
    hasAns = False
    
    #邏輯運算結果
    if( (a & b) == c ):
      print("AND")
      hasAns = True

    if( (a | b) == c ):
      print("OR")
      hasAns = True

    if( (a ^ b) == c ):
      print("XOR")
      hasAns = True

    if( hasAns == False ):
      print("IMPOSSIBLE")

最後放個艾鍗科技對此題的解說影片:


APCS 實作題 10706 第1題特殊編碼參考解法

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

此題為APCS 2018 年 6 月檢測的第一題,題目來源為吳邦一老師所提供的「APCS 2018 年6 月實作題檢測題目分析與解答」,題目內容如下:
此題在高中生程式解題系統的題號為:e283: APCS 類似題 - 小崴的特殊編碼
筆者採取比較取巧的方式:「查表法」。於是就用字典來實作,Python程式碼如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 讀取正整數 N
n = int(input())

# 字母編碼的對應表
decodeL = {
    '0 1 0 1': 'A',
    '0 1 1 1': 'B',
    '0 0 1 0': 'C',
    '1 1 0 1': 'D',
    '1 0 0 0': 'E',
    '1 1 0 0': 'F'
    }

num = []

# 讀取每一行的字母編碼
for i in range(n):
    num.append(input())

# 查表輸出對應的字母
for i in range(n):
    print(decodeL[num[i]], end='')
註:此Python在高中生解題系統會拿到 83% 的分數,要怎麼修改成 100%呢?

Python 程式碼第二版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import sys

# 字母編碼的對應表
decodeL = {
    '0 1 0 1': 'A',
    '0 1 1 1': 'B',
    '0 0 1 0': 'C',
    '1 1 0 1': 'D',
    '1 0 0 0': 'E',
    '1 1 0 0': 'F'
    }

num = []

for i in sys.stdin:
    # 讀取正整數 N
    n = int(i)
    result = ''

    # 讀取每一行的字母編碼
    for i in range(n):
        k = sys.stdin.readline().strip()
        result += decodeL[k]

    # 查表輸出對應的字母
    print(result)

C++程式碼如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <map>
#include <vector>
#include <string>
using namespace std;

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  // 建立字母編碼表
  std::map<std::string, std::string> lDict;
  lDict["0 1 0 1"] = "A";
  lDict["0 1 1 1"] = "B";
  lDict["0 0 1 0"] = "C";
  lDict["1 1 0 1"] = "D";
  lDict["1 0 0 0"] = "E";
  lDict["1 1 0 0"] = "F";

  // 讀取正整數 n
  int n;
  while(cin >> n)
  {
    // get the return character
    cin.get();

    vector<string> lVec;
    string encodeStr;

    for(int i = 0; i < n; i++) {
        getline(std::cin, encodeStr);
        lVec.push_back(encodeStr);
    }

    for(int i = 0; i < n; i++) {
        encodeStr = lVec[i];
        cout << lDict[encodeStr];
    }

    cout << "\n";
  }

  return 0;
}

Java程式碼如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.*; 

class Main {
  public static void main(String[] args) {
    Dictionary lDict = new Hashtable();
    lDict.put("0 1 0 1", "A");
    lDict.put("0 1 1 1", "B");
    lDict.put("0 0 1 0", "C");
    lDict.put("1 1 0 1", "D");
    lDict.put("1 0 0 0", "E");
    lDict.put("1 1 0 0", "F");

    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    scanner.nextLine();
    
    String str;
    Vector<String> strVec = new Vector<String>();
    
    for(int i = 0; i < n; i++) {
      str = scanner.nextLine();
      strVec.add(str);
    }

    for(int i = 0; i < n; i++) {
      System.out.print(lDict.get(strVec.get(i)));
    }
  }
}

除了吳邦一老師所用的方法與查表法之外,我們還可以有什麼方法呢?

APCS 檢測系統環境導覽

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

本篇文章是根據APCS官網檢測系統環境(https://apcs.csie.ntnu.edu.tw/index.php/info/environment/)來建立環境。建立好後,登入畫面如下:

看起來有提供範例程式,以及相關程式語言的開發環境,而根據官網的說明,會提供底下軟體:

那筆者就來實際測試看看囉。首先略過不是關注的重點:OS和Desktop。

Editors
點選桌面的Leafpad圖示,並開啟 P3.cpp 檔案。


開啟LXTerminal,並執行Vim。

看來 Editor 是沒問題的。

Languages
下圖適用指令的方式列出C、C++、Java、Python語言版本。

這也沒問題。

IDE
IDE是軟體開發者常用的工具,用IDE才有機會方便除錯,先試試支援最多程式語言的Eclipse,版本為 https://www.eclipse.org/downloads/packages/release/oxygen/3。預設是Java語言。

筆者從Create New Project找看看有沒有除了Java以外的C、C++、Python專案。

發現沒有支援Java語言之外的C、C++、Python專案。要如何使用Eclipse 來做Java除錯,可參考這篇:eclipse-執行-debug-除錯模式

再來是支援C、C++的Code::Blocks

Code::Blocks的除錯方式可觀看這部影片。或是這篇教學文章:CodeBlock除錯


最後是Python語言用的IDLE。

IDLE的除錯方式可參考這篇:如何使用IDLE進行除錯

結言:
要考APCS的人,一定要先知道考場提供了那些軟硬體,以免上考場時,不知道怎麼操作,那就尷尬啦!

讀書筆記:深入淺出設計模式 (HEAD FIRST DESIGN PATTERNS)

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

此文為筆者在閱讀【深入淺出設計模式(Head First Design Patterns) 」一書所作的筆記。

設計模式種類:
策略模式(Strategy Pattern):定義演算法家族,個別封裝起來,讓它們之間可以交互替換,此模式讓演算法的變動,不會影響到使用演算法的程式。

觀察者模式(Observer Pattern)出版者 + 訂閱者 = 觀察者模式。『觀察者模式』定義了物件之間的一對多關係,如此一來,當一個物件改變狀態,其他相依者都會收到通知並自動被更新。

裝飾者模式(Decorator Pattern)動態地將責任加諸於物件上。若要擴充功能,裝飾者提供了比繼承更有彈性的選擇。

工廠方法模式(Factory Method Pattern)定義了一個建立物件的介面,但由次類別決定要實體化的類別為何者。工廠方法讓類別把實體化的動作,交由次類別進行。

抽象工廠模式(Abstract Factory Pattern)提供了一個介面,建立相關或相依物件之家族,而不需要明確指定具象類別。

獨體模式(Singleton Pattern)確保一個類別只有一個實體,並給它一個存取的全域點(global point)。

命令模式(Command Pattern)將「請求」封裝成物件,以便使用不同的請求、佇列、或者日誌,參數化其他物件。命令模式也支援可復原的作業。

轉接器模式(Adapter Pattern)將一個類別的介面,轉換成另一個介面以供客戶使用。轉接器讓原本介面不相容的類別可以合作無間。

表象模式(Facade Pattern)提供了一個統一的介面,用來存取次系統中的一群介面。表象定義了一個較高層次的介面,讓次系統更容易使用。

樣板方法模式(Template Method Pattern)將一個演算法的骨架定義在一個方法中,而演算法本身會用到的一些方法,則是定義在次類別中。樣板方法讓次類別在不改變演算法架構的情況下,重新定義演算法中的某些步驟。


設計守則:
    一、找出程式中可能需要更動之處,把它們獨立出來,不要和那些不需要更動的程式碼混在一起。把會變動的部分取出並『封裝』起來,好讓其他部分不會受到影響。
『把會變動的部分取出並封裝起來,以便以後可以輕易地擴充此部分,而不影響不需要更動的其他部分。」

    二、寫程式是針對介面而寫,而不是針對實踐方式而寫。

    三、多用合成,少用繼承。

    四、設計時,盡量讓需要互動的物件之間關係鬆綁。

    五、類別應該開放,以便擴充;應該關閉,禁止修改。雖然似乎有點矛盾,但是的確有一些技術可以允許程式碼,在不直接修改的情況下進行擴充。小心地選擇哪些部分以後可能需要被擴充。到處採用開放關閉守則,是一種浪費也沒必要,而且會導致程式碼變得複雜且難以讀取。

    六、依賴抽象類別,不要依賴具象類別。

    七、認識極少化守則「只和你的密友談話」。

    八、好萊塢守則「別呼叫(打電話給)我們,我們會呼叫(打電話給)你。」

Python Puzzler 12: ABC

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

底下的Java程式碼會有什麼結果?
1
2
3
4
5
6
7
public class Abc {
    public static void main(String[] args) {
        String letters = "ABC";
        char[] numbers = { '1', '2', '3' };
        System.out.println(letters + " easy as " + numbers);
    }
}

使用JDK11.0.2的結果為 ABC easy as [C@5c8da962 。這是因為 numbers 是 ,而字元陣列會呼叫Object的toString(),但我們沒有將toString() method 給 Overwrite,於是會得到一組Hash code的數值。     

那我們來看看在Python裡,會有什麼結果?
1
2
3
letters = "ABC"
numbers = { '1', '2', '3' }
print(letters + " easy as " + numbers)

上述的程式碼會得到下面的錯誤訊息:
1
2
    print(letters + " easy as " + numbers)
TypeError: can only concatenate str (not "set") to str

這是因為在 Python 裡,{ '1', '2', '3' } 會是集合(set)的語法。而且因為 letters 是str,所以 + 會被當成字串合併來執行。

寫程式用的雲端 IDE(Cloud IDE for Programming)

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

要寫程式之前,得先將工具準備好,當所使用的程式語言有好多種,那前置作業就會很多,若只是要練習語法之類的話,那麼雲端 IDE 是個不錯的選擇,目前常見免費且不用建立帳號的雲端 IDE 有下面幾個:

Here are some cloud IDEs for programming. And we don't need a account to use them.

  1. ideone: http://ideone.com/,教學:https://www.techmarks.com/ideone-online-coding/
  2. codepad: http://codepad.org/,教學:https://www.youtube.com/watch?v=8izi7QDEOHk
  3. CodePen:  http://codepen.io/,教學:https://www.minwt.com/webdesign-dev/html/11470.html
  4. JSFiddle: https://jsfiddle.net/,教學:https://blog.miniasp.com/post/2011/02/07/Useful-tool-jsFiddle-Online-Editor-for-the-Web
  5. Tutorialspoint: http://www.tutorialspoint.com/codingground.htm,教學:https://codegym.tech/coding-ground/
  6. Jdoodle: https://www.jdoodle.com/,教學:https://www.youtube.com/watch?v=idN5QmUS8-8

其中的 Tutorialspoint 網站所提供的工具最完整,它除了多樣的程式語言外,還提供了一些 Terminal,如 MySQL、PowerShell、Node.js 等,此外 Tutorialspoint 也有豐富的教學資料,值得一看。 另外 CodePen 和 JSFiddle 只提供前端開發用的JavaScript + HTML + CSS。至於這些雲端 IDE 的使用方式大同小異,先在網頁上寫完程式碼,之後再按下類似 Run 的按鈕就行了。 祝各位 Happy Coding。

Python Expressive Puzzlers 8: Does Equal

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

底下的Java程式會輸出什麼結果?
1
2
3
4
5
6
7
8
public class DosEquis {
  public static void main(String[] args) {
    char x = 'X';
    int i = 0;
    System.out.print(true  ? x : 0);
    System.out.print(false ? i : x); 
  }
}

輸出結果會是XX嗎?根據 JLS 15.25的說明(true ? x : 0)的運算結果會是char型別,而(false ? i : x)的運算結果會是int型別。所以輸出結果為X88

而 Python 只有 <expression1> if <condition> else <expression2>的語法,沒有 Java 的 conditional operator 的語法,於是不會有這樣子的Pitfall。

Python Expressive Puzzlers 7: Swap

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

底下兩個Java Class分別會輸出什麼結果?
1
2
3
4
5
6
7
8
public class CleverSwapOne {
  public static void main(String[] args) {
    int x = 1984;
    int y = 2001;
    x ^= y ^= x ^= y;
    System.out.println("x = " + x + "; y = " + y);
}
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class CleverSwapTwo {
  public static void main(String[] args) {
    int x = 1984;
    int y = 2001;
    x ^= y;
    y ^= x;
    x ^= y;
    System.out.println("x = " + x + "; y = " + y);
  }
}
CleverSwapOne會輸出x = 0; y = 1984,而CleverSwapTwo會輸出x = 2001; y = 1984。為什麼會這樣子呢?

根據JLS 15.7 的說明:「Evaluate Left-Hand Operand First」也就是CleverSwapOne 的執行順序如下:
1
2
3
4
5
6
7
// The actual behavior of x ^= y ^= x ^= y in Java
int tmp1 = x; // First appearance of x in the expression
int tmp2 = y; // First appearance of y
int tmp3 = x ^ y; // Compute x ^ y
x = tmp3; // Last assignment: Store x ^ y in x
y = tmp2 ^ tmp3; // 2nd assignment: Store original x value in y
x = tmp1 ^ y; // First assignment: Store 0 in x

如同原作所說:「 Do not assign to the same variable more than once in a single expression.」

那Python呢?
1
2
3
4
5
6
7
8
9
x = 1984
y = 2001

x ^= y
y ^= x
x ^= y

x ^= y ^= x ^= y
print('x = ', x, 'y = ',  y)

Python Expressive Puzzlers 6: Multicast

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

底下的Java程式會輸出什麼?
1
2
3
4
5
public class Multicast {
  public static void main(String[] args) {
    System.out.println((int) (char) (byte) -1);
}
}

結果不會是 -1。幸運的是有條簡單的規則來說明:「Sign extension is performed if the type of the original value is signed; zero extension if it is a char, regardless of the type to which it is being converted.」也就是 byte -1  === sign extension ==> char 65535 === zero extension ==> int 65535。

而 Python Built-in type 不多,筆者只試了底下兩行:
print(int(str(bytes(-1))))
print(int(chr(bytes(-1))))

輸出結果會是什麼呢?