Category: LẬP TRÌNH

  • Dart Cheat Sheet and Quick Reference

    Dart Cheat Sheet and Quick Reference

    Dart Cheat Sheet and Quick Reference

    Source: raywenderlich.com

    main() function

    void main() {
       print('Hello, Dart!');
    }

    Variables, Data Types, & Comments

     
    // Use var with type inference or instead use type name directly
    var myAge = 35; // inferred int created with var
    var pi = 3.14; // inferred double created with var
    int yourAge = 27; // type name instead of var
    double e = 2.718; // type name instead of var
    
    // This is a comment
    print(myAge); // This is also a comment.
    
    /*
    And so is this.
    */
    
    // dynamic can have value of any type
    dynamic numberOfKittens;
    
    // dynamic String
    numberOfKittens = 'There are no kittens!';
    numberOfKittens = 0; // dynamic int
    numberOfKittens = 1.0; // dynamic double
    bool areThereKittens = true; // bool
    
    // Compile-time constants
    const speedOfLight = 299792458;
    
    // Immutables with final
    final planet = 'Jupiter';
    
    // planet = 'Mars'; // error: planet is immutable
    // Enumerations
    enum Month { january, february, march, april, may, june, july, august, september, october, november, december }
    final month = Month.august;

    Null

    int age; // initialized to null
    double height;
    String err;
    
    // Check for null
    var error = err ?? "No error"; // No error
    
    // Null-check compound assignment
    err ??= error;
    
    // Null-check on property access
    print(age?.isEven);

    Operators

    // Arithmetic
    40 + 2; // 42
    44 - 2; // 42
    21 * 2; // 42
    84 / 2; // 42
    84.5 ~/ 2.0; // int value 42
    392 % 50; // 42
    
    // Types can be implicitly converted
    var answer = 84.0 / 2; // int 2 to double
    
    // Equality and Inequality
    42 == 43; // false
    42 != 43; // true
    
    // Increment and decrement
    print(answer++); // 42, since it prints first for postfix
    print(--answer); // 42, since it decrements first for prefix
    
    // Comparison
    42 < 43; // true
    42 > 43; // false
    42 <= 43; // true
    42 >= 43; // false
    
    // Compound assignment
    answer += 1; // 43
    answer -= 1; // 42
    answer *= 2; // 84
    answer /= 2; // 42
    
    // Logical
    (41 < answer) && (answer < 43); // true
    (41 < answer) || (answer > 43); // true
    !(41 < answer)); // false

    Strings

    // Can use single or double quotes for String type
    var firstName = 'Albert';
    String lastName = "Einstein";
    
    // Escape sequences such as \' and \n
    // and concatenating adjacent strings
    var quote = 'If you can\'t' ' explain it simply\n'
    "you don't understand it well enough.";
    
    // Concatenation with +
    var energy = "Mass" + " times " + "c squared";
    
    // Preserving formatting with """
    var model = """
    I'm not creating the universe.
    I'm creating a model of the universe,
    which may or may not be true.""";
    
    // Raw string with r prefix
    var rawString =r”I'll\nbe\nback!"; // prints I’ll\nbe\nback!

    Control Flow: Conditionals

    var animal = 'fox';
    if (animal == 'cat' || animal == 'dog') {
       print('Animal is a house pet.');
    } else if (animal == 'rhino') {
       print('That\'s a big animal.');
    } else {
       print('Animal is NOT a house pet.');
    }
    
    // switch statement
    enum Semester { fall, spring, summer }
    Semester semester;
    
    switch (month) {
       case Month.august:
       case Month.september:
       case Month.october:
       case Month.november:
       case Month.december:
          semester = Semester.fall;
          break;
       case Month.january:
       case Month.february:
       case Month.march:
       case Month.april:
       case Month.may:
          semester = Semester.spring;
          break;
       case Month.june:
       case Month.july:
          semester = Semester.summer;
          break;
    }

    Control Flow: While loops

    var i = 1;
    // while, print 1 to 9
    while (i < 10) {
        print(i);
        i++;
    }
    
    // do while, print 1 to 9
    i = 1;
    do {
        print(i);
        ++i;
    }
    while (i < 10);
    // break at 5
    do {
       print(i);
       if (i == 5) {
       break;
    }
    ++i;
    } while (i < 10);

    Control Flow: For loops

    var sum = 0;
    // Init; condition; action for loop
    for (var i = 1; i <= 10; i++) {
    sum += i;
    }
    
    // for-in loop for list
    var numbers = [1, 2, 3, 4];
    for (var number in numbers) {
    print(number);
    }
    
    // Skip over 3 with continue
    for (var number in numbers) {
    if (number == 3) {
    continue;
    }
    print(number);
    }
    
    // forEach with function argument
    numbers.forEach(print); // 1, 2, 3, 4 on separate lines
    
    // forEach with anonymous function argument
    numbers = [13, 14, 15, 16];
    numbers.forEach((number) => print(number.toRadixString(16)); // d, e, f, 10

    Functions

    // Named function
    bool isBanana(String fruit) {
    return fruit == 'banana';
    }
    
    var fruit = 'apple';
    isBanana(fruit); // false
    
    // Optional parameters with square brackets
    String fullName(String first, String last, [String title]) {
    return "${title == null ? "" : "$title "}$first
    $last";
    }
    fullName("Ray", "Wenderlich"); // Ray Wenderlich
    fullName("Albert", "Einstein", "Professor"); //Professor Albert Einstein
    
    // Optional named arguments with braces
    bool withinTolerance(int value, {int min, int max}) {
    return (min ?? 0) <= value && value <= (max ??
    10);
    }
    withinTolerance(11, max: 10, min: 1); // false
    
    // Default values
    bool withinTolerance(int value, {int min = 0, int max = 10}) {
    return min <= value && value <= max;
    }
    withinTolerance(5); // true
    
    // Function as parameter
    int applyTo(int value, int Function(int) op) {
    return op(value);
    }
    int square(int n) {
    return n * n;
    }
    applyTo(3, square); // 9
    
    // Arrow syntax for one line functions
    int multiply(int a, int b) => a * b;
    multiply(14, 3); // 42

    Anonymous Functions and Closures

    // Anonymous functions (without a name)
    // Assign anonymous function to a variable
    var multiply = (int a, int b) {
    return a * b;
    }
    
    // Call a function variable
    multiply(14, 3); // 42
    
    // Closures
    Function applyMultiplier(num multiplier){
    
    // Return value has access to multiplier
    return (num value) => value * multiplier;
    }
    var triple = applyMultiplier(3);
    triple(14.0); // 42.0

    Collections: Lists

    // Fixed-size list
    var pastries = List<String>(3);
    
    // Element access by index
    pastries[0] = 'cookies';
    pastries[1] = 'cupcakes';
    pastries[2] = 'donuts';
    
    // Growable list
    List<String> desserts = [];
    desserts.add('cookies');
    
    // Initialize by growable list
    var desserts = ['cookies', 'cupcakes', 'pie'];
    
    // List properties and methods
    desserts.length; // 3
    desserts.first; // 'cookies'
    desserts.last; // 'pie'
    desserts.isEmpty; // false
    desserts.isNotEmpty; // true
    desserts.firstWhere((str) => str.length < 4));// pie
    
    // Collection if
    var peanutAllergy = true;
    var candy = ['junior mints', 'twizzlers', if (!peanutAllergy) 'reeses'];
    
    // Collection for
    var numbers = [1, 2, 3];
    var doubledNumbers = [for (var number in numbers) 2 * number]; // [2, 4, 6]

    Collections: List Operations

    // Spread Operator and null-spread operator
    var pastries = ['cookies', 'cupcakes'];
    var desserts = ['donuts', ...pastries, ...?candy];
    
    // Map to transform list
    var numbers = [1, 2, 3, 4];
    var squares = numbers.map((number) => number * number).toList(); // [1, 4, 9, 16]
    
    // Filter list using where
    var evens = squares.where((square) => square.isEven); // (4, 16)
    
    // Reduce list to combined value
    var amounts = [199, 299, 299, 199, 499];
    var total = amounts.reduce((value, element) => value + element); // 1495

    Collections: Sets

    // Create set of int
    var someSet = <int>{};
    
    // Set type inference
    var anotherSet = {1, 2, 3, 1};
    
    // Check for element
    anotherSet.contains(1); // true
    anotherSet.contains(99); // false
    
    // Adding and removing elements
    someSet.add(42);
    someSet.add(2112);
    someSet.remove(2112);
    
    // Add to set from list
    someSet.addAll([1, 2, 3, 4]);
    
    // Intersection
    var intersection = someSet.intersection(anotherSet);
    
    // Union
    var union = someSet.union(anotherSet);

    Collections: Maps

    // Map from String to int
    var emptyMap = Map<String, int>();
    
    // Map from String to String
    var avengers = {"Iron Man": "Suit", "Captain America": "Shield", "Thor": "Hammer"};
    
    // Element access by key
    var ironManPower = avengers["Iron Man"]; // Suit
    avengers.containsKey("Captain America"); // true
    avengers.containsValue("Arrows"); // false
    
    // Access all keys and values
    avengers.keys.forEach(print); // Iron Man, Captain America, Thor
    avengers.values.forEach(print); // Suit, Shield, Hammer
    
    // Loop over key-value pairs
    avengers.forEach((key, value) => print('$key -> $value'));

    Classes and Objects

    class Actor {
    
    // Properties
    String name;
    var filmography = <String>[];
    
    // Short-form constructor
    Actor(this.name, this.filmography);
    
    // Named constructor
    Actor.rey({this.name = "Daisy Ridley"}) {
    filmography = ['The Force Awakens', 'Murder on the Orient Express'];
    }
    
    
    // Calling other constructors
    Actor.inTraining(String name) : this(name, []);
    
    // Constructor with initializer list
    Actor.gameOfThrones(String name): this.name = name, this.filmography = ['Game of Thrones'] {
    print('My name is ${this.name}');
    }
    
    // Getters and Setters
    String get debut => '$name debuted in ${filmography.first}';
    set debut(String value) => filmography.insert(0, value);
    
    // Methods
    void signOnForSequel(String franchiseName) {
    filmography.add('Upcoming $franchiseNamesequel');
    }
    
    // Override from Object
    String toString() => "${[name, ...filmography].join("\n- ")}\n";
    }
    var gotgStar = Actor('Zoe Saldana', []);
    gotgStar.name = 'Zoe Saldana';
    gotgStar.filmography.add('Guardians of the Galaxy');
    gotgStar.debut = 'Center Stage';
    print(Actor.rey().debut); // The Force Awakens
    var kit = Actor.gameOfThrones('Kit Harington');
    var star = Actor.inTraining('Super Star');
    
    // Cascade syntax ..
    gotgStar // Get an object
    ..name = 'Zoe' // Use property
    ..signOnForSequel('Star Trek'); // Call method

    Static Class Members

    enum PhysicistType { theoretical, experimental, both
    }
    class Physicist {
    String name;
    PhysicistType type;
    
    // Internal constructor
    Physicist._internal(this.name, this.type);
    
    // Static property
    static var physicistCount = 0;
    
    // Static method
    static Physicist newPhysicist(
    String name,
    PhysicistType type) {
    physicistCount++;
    return Physicist._internal(name, type);
    }
    }
    final emmy = Physicist.newPhysicist(
    "Emmy Noether", PhysicistType.theoretical);
    final lise = Physicist.newPhysicist(
    "Lise Meitner", PhysicistType.experimental);
    print(Physicist.physicistCount); //2

    Class Inheritance

    // Base aka parent class
    class Person {
    
    // Parent properties inherited by child
    String firstName;
    String lastName;
    
    // Parent class constructor
    Person(this.firstName, this.lastName);
    
    // Parent class method
    String get fullName => '$firstName $lastName';
    
    // Optional @override annotation
    // All class hierarchies and types have Object as root class
    @override
    String toString() => fullName;
    }
    
    // Subclass aka child class
    class Student extends Person {
    
    // Properties specific to child
    var grades = <String>[];
    
    // Call super on parent constructor
    Student(String firstName, String lastName): super(firstName, lastName);
    
    // Optional override annotation on parent method override
    @override
    String get fullName => '$lastName, $firstName';
    }
    final jon = Person('Jon', 'Snow');
    final jane = Student('Jane', 'Snow'); // Calls parent constructor
    print(jon); // Jon Snow
    
    // Use toString in parent, in turn using subclass override of fullName
    print(jane); // Snow, Jane

    Abstract Classes, Interfaces, Mixins

    enum BloodType { warm, cold }
    abstract class Animal {
    BloodType bloodType; // Base class property
    void goSwimming(); // Abstract method without implementation
    }
    mixin Milk {
    bool hasMilk;
    bool doIHaveMilk() => hasMilk;
    }
    
    // Concrete class inheriting from abstract class
    class Cat extends Animal with Milk {
    BloodType bloodType = BloodType.warm; // Set value for property
    Cat() { hasMilk = true; } // Set mixin property
    
    // Concrete subclass must implement abstract methods
    @override
    void goSwimming() { print("No thanks!"); }
    }
    
    // Concrete class that also implements Comparable interface
    class Dolphin extends Animal implements
    Comparable<Dolphin> {
    BloodType bloodType = BloodType.warm;
    double length; // Concrete sublcass property
    Dolphin(this.length); // Concrete subclass constructor
    
    // Concrete subclass must implement abstract methods
    @override
    void goSwimming() { print("Click! Click!"); }
    
    // Also must implement interface methods
    @override
    int compareTo(other) =>
    length.compareTo(other.length);
    @override
    String toString() => '$length meters';
    }
    class Reptile extends Animal with Milk {
    BloodType bloodType = BloodType.cold;
    Reptile() { hasMilk = false; }
    @override
    void goSwimming() { print("Sure!"); }
    }
    
    // var snake = Animal(); // error: can't instantiate abstract class
    // Can instantiate concrete classes
    var garfield = Cat();
    var flipper = Dolphin(4.0);
    var snake = Reptile();
    
    // Call concrete methods
    flipper.goSwimming(); // Click! Click!
    garfield.goSwimming(); // No thanks!
    
    // Use interface implementation
    var orca = Dolphin(8.0); var alpha = Dolphin(5.0);
    var dolphins = [alpha, orca, flipper];
    dolphins.sort();
    print(dolphins); // [4 meters, 5 meters, 8 meters]
    print(snake.doIHaveMilk()); // false
    print(garfield.doIHaveMilk()); // true

     

  • How to download and reinstall Realtek HD Audio Manager in Windows 10

    How to download and reinstall Realtek HD Audio Manager in Windows 10

    How to download and reinstall Realtek HD Audio Manager in Windows 10

  • Python: Bài toán xếp hậu sử dụng đệ quy

    Python: Bài toán xếp hậu sử dụng đệ quy

    Python: Bài toán xếp hậu sử dụng đệ quy

    Bài toán xếp hậu là một bài toán kinh điển thường được giới thiệu trong các cuốn sách về thuật toán. Ở đây, chúng ta sẽ giải quyết bài toán bằng các sử dụng giải thuật đệ quythuật toán quay lui (vét cạn).

    Xem thêm: Thuật toán giải sudoku bằng quay lui backtracking

    Xét bàn cờ tổng quát kích thước nxn. Một quân hậu trên bàn cờ có thể ăn được các quân khác nằm tại các ô cùng hàng, cùng cột hoặc cùng đường chéo. Hãy tìm các xếp n quân hậu trên bàn cờ sao cho không quân nào ăn quân nào.

    Ví dụ một cách xếp với n = 8

    bài toán xếp hậu với n=8

    1. Giải bài toán xếp hậu sử dụng đệ quy

    Để giải quyết bài toán xếp 8 quân hậu này, chúng ta sử dụng list (mảng) a có kích thước bằng 8 với quy ước a[i]=j để đánh dấu vị trí xếp quân hậu thuộc dòng i ở cột thứ j.

    1.1. Tạo danh sách để lưu vị trí các quân hậu

    Để khởi tạo mảng a, chúng ta dùng lệnh

    n = 8
    a = n*[0]

    Lưu ý rằng các list danh sách trong Python được đánh chỉ số từ 0, do đó vị trí của quân hậu ở dòng thứ nhất được lưu ở a[0]

    Ví dụ a=[0, 4, 7, 5, 2, 6, 1, 3]có ý nghĩa, quân hậu ở dòng thứ nhất sẽ ở cột thứ nhất, quân hậu ở dòng thứ hai sẽ ở cột thứ 5, quân hậu ở dòng thứ 3 sẽ ở cột thứ 8…

    1.2. Viết hàm in vị trí các quân hậu dạng ma trận

    Chúng ta sẽ viết một hàm print_board() để in ra màn hình vị trí các quân hậu dạng ma trận (bảng), ví dụ với mảng a ở trên, in ra màn hình được:

    1 0 0 0 0 0 0 0 
    0 0 0 0 1 0 0 0 
    0 0 0 0 0 0 0 1 
    0 0 0 0 0 1 0 0 
    0 0 1 0 0 0 0 0 
    0 0 0 0 0 0 1 0 
    0 1 0 0 0 0 0 0 
    0 0 0 1 0 0 0 0

    Hàm in vị trí các quân hậu như sau:

    def print_board(b):
       l = len(b)
       for i in range(l):
          for j in range(l):
             if j == a[i]:
                print(1, end = " ")
             else:
                print(0, end = " ")
          print()

    1.3. Viết hàm kiểm tra vị trí (d,c) có còn đặt được quân hậu mới không?

    Chúng ta quy ước dc là vị trí của dòng và cột đang xét để xem có khả năng đặt được quân hậu mới hay không.

    Rõ ràng, ta chỉ cần kiểm tra xem trong các dòng từ 0 tới d-1 đã có quân hậu nào mà có thể ăn được quân hậu nếu đặt ở ô đang xét hay không, do đó chỉ cần duyệt từ các dòng có chỉ số thuộc range(d).

    Chúng ta viết hàm possible(d,c) để kiểm tra vị trí d,c còn có khả năng đặt hậu hay không. Khi đó, kết quả trả về là False nếu một trong 3 khả năng sau xảy ra:

    • Tại cột c đã có quân hậu ở dòng i nào đó, điều kiện là a[i] == c
    • Tại 2 đường chéo đi qua điểm (d,c) đã có một quân hậu nào đó.

    Lưu ý rằng các đường chéo sẽ song song hoặc trùng với các tia phân giác của góc phần tư trong hệ tọa độ Oxy. Các tia phân giác có phương trình là y = x hoặc y = - x. Do đó phương trình các đường chéo đi qua điểm có tọa độ (d,c) sẽ là c - d =y -x  hoặc c + d = y  + x. Từ đó suy ra điều kiện:

    a[i] == c  or c - d == a[i] - i or c + d == a[i] + i

    Mã nguồn của hàm kiểm tra vị trí có thể đặt hậu như sau:

    def possible(x, y):
       for i in range(x):      
          if a[i] == y  or y - x == a[i] - i or y + x == a[i] + i:
             return False
       return True

    1.4. Hàm đệ quy để sinh ra các vị trí đặt quân hậu

    def gen(i, n):
       for j in range(n):
          if possible(i,j):
             a[i] = j
             if i == n - 1:
                print(a)
             gen(i+1, n)

    Chương trình bắt đầu với lời gọi gen(0, n).

    Mã nguồn hoàn chỉnh bằng Python của bài toán xếp hậu như sau:

    n = 8
    a = n*[0]
    
    def print_board(b):
       l = len(b)
       for i in range(l):
          for j in range(l):
             if j == a[i]:
                print(1, end = " ")
             else:
                print(0, end = " ")
          print()
    
    def possible(d, c):
       for i in range(d):
          # if a[i] == y or abs(i - x) == abs(a[i] - y):
          if a[i] == c  or c - d == a[i] - i or c + d == a[i] + i:
             return False
       return True
    
    def gen(i, n):
       for j in range(n):
          if possible(i,j):
             a[i] = j
             if i == n - 1:
                print(a)
             gen(i+1, n)
    
    gen(0, n)

    Kết quả trả về là tất cả các phương án mỗi phương án là một danh sách chứa vị trí các quân hậu. Nếu muốn in một phương án nào đó, chúng ta sử dụng hàm print_board()

    2. Bài toán xếp hậu quay lui

    Chúng tôi giới thiệu thêm bài toán xếp hậu sử dụng thuật toán quay lui để bạn đọc tham khảo. Cách làm này có thời gian chạy khá chậm, và mỗi lần chỉ in ra một phương án xếp các quân hậu. Muốn tìm được phương án khác, chúng ta cần thay đổi giá trị của mảng board ban đầu.

    Cách giải này tôi có tham khảo từ bài viết này.

    board = [
          [0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0]
          ]
    
    
    def print_board(bo):
        for d in bo:        
            for c in d:
                print(c, end = " ")
            print()
    
    
    def solve(bo):
       l = len(bo)
       for d in range(l):
          for c in range(l):
             if bo[d][c] == 0:
                if possible(bo, d, c):
                   bo[d][c] = 1
                   solve(bo)
                if sum(sum(a) for a in bo) == l:
                   return bo
                else:
                   bo[d][c] = 0
       return bo		
    
    
    def possible(bo, d, c):
       l = len(bo)
       for i in range(l):
          if bo[i][c] == 1:
             return False
       for i in range(l):
          if bo[d][i] == 1:
             return False
       for i in range(l):
          for j in range(l):
             if bo[i][j] == 1:
                if c-d == j-i or c+d == i+j:
                   return False
       return True
    
    solve(board)
    print_board(board)
  • Thuật toán giải sudoku bằng quay lui backtracking

    Thuật toán giải sudoku bằng quay lui backtracking

    Thuật toán giải sudoku bằng quay lui backtracking

    Trong bài này chúng ta sẽ sử dụng thuật toán quay lui để giải quyết bài toán giải Sudoku. Để hiểu thuật toán quay lui là gì mời bạn xem bài Thuật toán quay lui và minh họa.

    Xem thêm: Python: Bài toán xếp hậu sử dụng đệ quy

    Bài viết tham khảo từ techwithtim.net

    1. Giới thiệu luật chơi và cách giải Sudoku

    Sudoku là một trò chơi giải đố theo wiki định nghĩa như sau:

    Sudoku (数独すうどく (số độc) sūdoku?) (suːˈdoʊkuː/, /-ˈdɒ-/, /sə-/, ban đầu có tên gọi là Number Place) là một trò chơi câu đố sắp xếp chữ số dựa trên logic theo tổ hợp. Mục tiêu của trò chơi là điền các chữ số vào một lưới 9×9 sao cho mỗi cột, mỗi hàng, và mỗi phần trong số chín lưới con 3×3 cấu tạo nên lưới chính (cũng gọi là “hộp”, “khối”, hoặc “vùng”) đều chứa tất cả các chữ số từ 1 tới 9. Câu đố đã được hoàn thành một phần, người chơi phải giải tiếp bằng việc điền số. Mỗi câu đố được thiết lập tốt có một cách làm duy nhất.

    Cách giải trò chơi Sudoku, mời các bạn xem video hướng dẫn sau:

    2. Thuật toán giải Sudoku

    Sau đây ta sẽ tìm thuật toán giải Sudoku bằng kỹ thuật backtracking, ngôn ngữ lập trình sử dụng là Python. Các bước tiến hành như sau:

    • Viết hàm in câu đố Sudoku ra màn hình.
    • Tìm vị trí các ô trống trong Sudoku.
    • Với mỗi vị trí ô trống vừa tìm được, lần lượt thử đặt số từ 1 đến 9 vào ô trống đó. Kiểm tra xem sau khi thử đặt số đó vào ô trống đó thì có hợp lệ (thỏa mãn các điều kiện về luật chơi của Sudoku hay không). Nếu hợp lệ thì tiếp tục tìm các ô trống tiếp theo và lại thử, nếu không thì thử với số_tiếp_theo
    • Lặp lại quy trình trên cho đến khi không còn ô trống nào trên câu đố, hoặc không tìm được lời giải.

    Input, một câu đố sudoku biểu diễn bởi danh sách list 2 chiều (một danh sách gồm 9 phần tử, mỗi phần tử là dòng – lại là một danh sách gồm 9 phần tử  tương ứng với 9 ô trong một dòng) với các ô trống được quy ước điền bởi số 0, ví dụ Sudoku cau_do được biểu diễn như sau:

    cau_do = [
        [7,8,0,4,0,0,1,2,0],
        [6,0,0,0,7,5,0,0,9],
        [0,0,0,6,0,1,0,7,8],
        [0,0,7,0,4,0,2,6,0],
        [0,0,1,0,5,0,9,3,0],
        [9,0,4,0,6,0,0,0,5],
        [0,7,0,3,0,0,0,1,2],
        [1,2,0,0,0,7,4,0,0],
        [0,4,9,2,0,6,0,0,7]
    ]

    Chú ý rằng chỉ số index trong Python được đánh từ 0 trở đi, do đó các vị trí của từng ô trong bảng số sẽ là cau_d0[0][0] cho đến cau_do[8][8], ở đây cau_do[d][c] là ô số ở vị trí dòng d và cột c.

    2.1. Viết hàm in câu đố Sudoku ra màn hình

    Ở đây chúng ta sử dụng giao diện dòng lệnh, chưa sử dụng giao diện đồ họa GUI nên sẽ sử dụng hàm print() của Python để in một đối tượng ra màn hình CMD.

    Ta sẽ viết hàm in_sudoku để in một câu đố Sudoku có tên là q ra màn hình, sử dụng biến dc để biểu diễn dòng và cột.

    Nếu dòng d là dòng thứ 3 hoặc 6 thì ta sẽ in ra màn hình một dòng gồm các kí tự - - - - - - - - - - - để ngăn cách, mục đích là biểu diễn cho các khối ô vuông 3x3 của Sudoku. Tương tự, nếu cột ở vị trí 3 hoặc 6 thì ta sẽ in ra kí tự | để ngăn cách. Nếu cột ở vị trí thứ 8 thì ta sẽ xuống dòng mới.

    def in_sudoku(q):
        for d in range(len(q)):
            if d % 3 == 0 and d != 0:
                print("- - - - - - - - - - -")
            for c in range(len(q[0])):
                if c % 3 == 0 and c != 0:
                    print("| ", end ="")
                if c == 8:
                    print(str(q[d][c]))
                else:
                    print(str(q[d][c]) + " ", end = "")

    Thử in với cau_do ở phần đầu, chúng ta được kết quả như sau, ở đây tôi dùng SublimeText để code:

    thuật toán giải sudoku

    2.2. Viết hàm tìm các ô trống trong Sudoku

    Mục tiêu của chúng ta là tìm các vị trí ô trống trong câu đố q

    def tim_o_trong(q):
        for d in range(len(q)):
            for c in range(len(q[0])):
                if q[d][c] == 0:
                    return d, c
        return None

    2.3.  Viết hàm kiểm tra tính hợp lệ của một câu đố

    def kiem_tra(q, gia_tri, dong, cot):
        for i in range(len(q[0])):
            if q[i][cot] == gia_tri and i != dong:
                return False
        for i in range(len(q)):
            if q[dong][i] == gia_tri and i != cot:
                return False
    
        x = cot // 3
        y = dong // 3
    
        for i in range(y*3, y*3+3):
            for j in range(x*3, x*3+3):
                if q[i][j] == gia_tri and i != dong and j != cot:
                    return False
        return True

    2.4. Viết hàm chính để tìm lời giải cho một câu đố Sudoku

    def giai(q):
        tim_thay = tim_o_trong(q)
        if not tim_thay:
            return True
        else:
            d, c = tim_thay
        for i in range(1,10):
            if kiem_tra(q, i, d, c):
                q[d][c] = i
                if giai(q):
                    return True
                else:
                    q[d][c] = 0
            
        return False

    3. Chương trình Python giải Sudoku hoàn chỉnh

    cau_do = [
        [7,8,0,4,0,0,1,2,0],
        [6,0,0,0,7,5,0,0,9],
        [0,0,0,6,0,1,0,7,8],
        [0,0,7,0,4,0,2,6,0],
        [0,0,1,0,5,0,9,3,0],
        [9,0,4,0,6,0,0,0,5],
        [0,7,0,3,0,0,0,1,2],
        [1,2,0,0,0,7,4,0,0],
        [0,4,9,2,0,6,0,0,7]
    ]
    
    def in_sudoku(q):
        for d in range(len(q)):
            if d % 3 == 0 and d != 0:
                print("- - - - - - - - - - -")
            for c in range(len(q[0])):
                if c % 3 == 0 and c != 0:
                    print("| ", end ="")
                if c == 8:
                    print(str(q[d][c]))
                else:
                    print(str(q[d][c]) + " ", end = "")
    
    
    def giai(q):
        tim_thay = tim_o_trong(q)
        if not tim_thay:
            return True
        else:
            d, c = tim_thay
        for i in range(1,10):
            if kiem_tra(q, i, d, c):
                q[d][c] = i
                if giai(q):
                    return True
                else:
                    q[d][c] = 0
            
        return False
            
        
    
    def tim_o_trong(q):
        for d in range(len(q)):
            for c in range(len(q[0])):
                if q[d][c] == 0:
                    return d, c
        return None
    
    
    def kiem_tra(q, gia_tri, dong, cot):
        for i in range(len(q[0])):
            if q[i][cot] == gia_tri and i != dong:
                return False
        for i in range(len(q)):
            if q[dong][i] == gia_tri and i != cot:
                return False
    
        x = cot // 3
        y = dong // 3
    
        for i in range(y*3, y*3+3):
            for j in range(x*3, x*3+3):
                if q[i][j] == gia_tri and i != dong and j != cot:
                    return False
        return True
    
    in_sudoku(cau_do)
    giai(cau_do)
    print('Loi giai cua Sudoku tren la:')
    in_sudoku(cau_do)

    Cho chạy chương trình, chúng ta được kết quả như hình sau:

    giải sudoku bằng Python

  • Thuật toán quay lui và minh họa

    Thuật toán quay lui và minh họa

    Thuật toán quay lui và minh họa

    1. Thuật toán quay lui là gì?

    Thuật toán quay lui (Backtracking) là một kĩ thuật thiết kế giải thuật dựa trên đệ quy. Ý tưởng của quay lui là tìm lời giải từng bước, mỗi bước chọn một trong số các lựa chọn khả dĩ và đệ quy. Người đầu tiên đề ra thuật ngữ này (backtrack) là nhà toán học người Mỹ D. H. Lehmer vào những năm 1950.

    2. Thuật toán quay lui sử dụng khi nào?

    Thuật toán quay lui thường được sử dụng để giải bài toán liệt kê các cấu hình (như bài toán sinh các xâu nhị phân). Mỗi cấu hình được xây dựng bằng cách xác định từng phần tử. Mỗi phần tử lại được chọn bằng cách thử tất cả các khả năng.
    Các bước trong việc liệt kê cấu hình dạng X[1…n]:
    • Xét tất cả các giá trị X[1] có thể nhận, thử X[1] nhận các giá trị đó. Với mỗi giá trị của X[1] ta sẽ:
    • Xét tất cả giá trị X[2] có thể nhận, lại thử X[2] cho các giá trị đó. Với mỗi giá trị X[2] lại xét khả năng giá trị của X[3]…tiếp tục như vậy cho tới bước:
    • Xét tất cả giá trị X[n] có thể nhận, thử cho X[n] nhận lần lượt giá trị đó.
    • Thông báo cấu hình tìm được.

    Để cài đặt thuật toán quay lui, chúng ta sử dụng một chương trình con (hàm function, thủ tục procedure) và gọi đến hàm đó trong chương trình chính của mình. Mô hình của thuật toán quay lui sử dụng ngôn ngữ Python như sau:

    def quay_lui(i):
       for j in [tập_các_phương_án_x[i] có thể nhận]:
          <thử đặt x[i] = j>
          if <x[i] là phần tử cuối cùng trong cấu hình>:
             <thông báo cấu hình>
          else:
             <ghi nhận việc cho x[i] nhận giá trị j nếu cần>
             <gọi đệ quy đến quay_lui(i+1)>
             <bỏ ghi nhận việc cho x[i] nhận giá trị j để thử giá trị khác nếu cần>

    Thuật toán quay lui sẽ bắt đầu bằng lời gọi quay_lui(1)

    3. Minh họa của thuật toán quay lui (Backtracking)

    3.1. Sử dụng thuật toán quay lui để sinh các dãy nhị phân độ dài n

    Dưới đây, chúng ta cùng xem mã chương trình sinh các dãy nhị phân có độ dài n bằng cách sử dụng thuật toán quay lui.

    n = 3
    x = n*[0]
    
    
    def fine_print(x):
       tmp = ''
       for i in x:
          tmp += str(i)
       return tmp
    
    
    def bin_gen(i):
       for j in range(0,3):
          x[i] = j
          if i == n-1:
             print(fine_print(x))
          else:
             bin_gen(i+1)
    
    bin_gen(0)

    Các giải khác bằng cách sử dụng vòng lặp, xin mời bạn đọc xem tại đây Thuật toán sinh các dãy nhị phân có độ dài n

    3.2. Sử dụng backtracking để giải Sudoku

    thuật toán giải sudoku

    Mời các bạn xem chi tiết trong bài Thuật toán giải sudoku bằng quay lui backtracking

    3.3. Sử dụng quay lui để giải bài toán xếp hậu

    Xét bàn cờ tổng quát kích thước nxn. Một quân hậu trên bàn cờ có thể ăn được các quân khác nằm tại các ô cùng hàng, cùng cột hoặc cùng đường chéo. Hãy tìm các xếp n quân hậu trên bàn cờ sao cho không quân nào ăn quân nào. Mời bạn xem chi tiết trong bài Python: Bài toán xếp hậu sử dụng đệ quy

    bài toán xếp hậu với n=8

    4. Đặc điểm của thuật toán quay lui

    Bản chất của quay lui là một quá trình tìm kiếm theo chiều sâu(Depth-First Search).
    • Ưu điểm: Việc quay lui là thử tất cả các tổ hợp để tìm được một lời giải. Thế mạnh của phương pháp này là nhiều cài đặt tránh được việc phải thử nhiều trường hợp chưa hoàn chỉnh, nhờ đó giảm thời gian chạy.
    • Nhược điểm: Trong trường hợp xấu nhất độ phức tạp của quay lui vẫn là cấp số mũ. Vì nó mắc phải các nhược điểm sau:
    • Rơi vào tình trạng “thrashing”: quá trình tìm kiếm cứ gặp phải bế tắc với cùng một nguyên nhân.
      • Thực hiện các công việc dư thừa: Mỗi lần chúng ta quay lui, chúng ta cần phải đánh giá lại lời giải trong khi đôi lúc điều đó không cần thiết.
      • Không sớm phát hiện được các khả năng bị bế tắc trong tương lai. Quay lui chuẩn, không có cơ chế nhìn về tương lai để nhận biết được nhánh tìm kiếm sẽ đi vào bế tắc.
  • Thuật toán sinh các dãy nhị phân có độ dài n

    Thuật toán sinh các dãy nhị phân có độ dài n

    Thuật toán sinh các dãy nhị phân có độ dài n

    Trong bài viết này chúng ta sẽ tìm cách liệt kê toàn bộ các dãy nhị phân có độ dài n cho trước.

    • Yêu cầu: Liệt kê tất cả các dãy nhị phân có độ dài n. (dãy nhị phân là dãy chỉ gồm hai số 01)
    • Input: Nhập vào n – độ dài của chuỗi nhị phân cần in ra.
    • Output : In ra màn hình tất cả các chuỗi nhị phân có độ dài n nhập từ đầu vào.

    Ví dụ:

    • Input: 3
    • Output:
    • 000   001   010   011   100   101   110   111

    1. Liệt kê các dãy nhị phân độ dài n bằng phương pháp sinh tuần tự

    Phương pháp sinh tuần tự sử dụng để liệt kê tất cả các phương án [cấu hình] của bài toán tổ hợp, sao cho các bài toán đó thỏa mãn:

    • Có thể xác định được một thứ tự trên tập các cấu hình tổ hợp cần liệt kê. Từ đó có thể biết đượccấu hình đầu tiên và cấu hình cuối cùng trong thứ tự đó.
    • Xây dựng được thuật toán từ một cấu hình chưa phải cấu hình cuối, sinh ra được cấu hình kế tiếp nó.

    Theo đó, thuật toán sinh tuần tự các cấu hình được mô tả như sau:

    <Xây dựng cấu hình đầu tiên>
    while True:
       <Đưa ra cấu hình đang có>
       <Từ cấu hình đang có sinh ra cấu hình kế tiếp nếu còn>
       if <hết cấu hình>:
          break

    Lưu ý rằng, Python không có câu lệnh điều khiển luồn repeat... until như một số ngôn ngữ khác, nên ta phải sử dụng vòng lặp while (Xem chi tiết trong bài Bài 7. Câu lệnh vòng lặp while trong Python)

    Vì kiểu xâu string là immutable nên chúng ta sẽ sử dụng kiểu danh sách list để thao tác trên đó, và định nghĩa hàm fine_print() để in toàn bộ các phần tử của danh sách dưới dạng xâu kí tự.

    Một lưu ý là các chỉ số index trong Python luôn được đánh số từ 0, do đó phần tử thứ nhất của một danh sách list x sẽ có chỉ số là 0, tức là phần tử x[0]

    n = 3
    s = n*[0]
    
    def fill_char(s,i):
       for j in range(i,n):
          s[j] = 0
    def fine_print(x):
       tmp = ''
       for i in x:
          tmp += str(i)
       return tmp
    
    
    while True:
       print(fine_print(s))
       i = n - 1
       while (i > -1) and s[i] == 1:
          i = i - 1
       s[i] = 1
       fill_char(s,i+1)
       if i == -1:
          break

    Kết quả thu được như sau:

    000
    001
    010
    011
    100
    101
    110
    111

    2. Sinh các dãy nhị phân độ dài n bằng thuật toán quay lui (Backtracking)

    liệt kê các chuỗi nhị phân bằng thuật toán quay lui

    Vẫn sử dụng kiểu danh sách list và hàm fine_print() như ở phần trên, chúng ta có chương trình liệt kê tất cả các xâu nhị phân có độ dài n sử dụng thuật toán quay lui như sau:

    n = 3
    x = n*[0]
    
    
    def fine_print(x):
       tmp = ''
       for i in x:
          tmp += str(i)
       return tmp
    
       
    def bin_gen(i):
       for j in range(0,2):
          x[i] = j
          if i == n-1:
             print(fine_print(x))
          else:
             bin_gen(i+1)
    
    bin_gen(0)

    Thuật toán quay lui có ưu điểm là rất dễ cài đặt so với phương pháp sinh tuần tự, hơn nữa có thể dễ dàng mở rộng để giải quyết nhiều bài toán khác nhau. Chẳng hạn, ta dễ dàng giải quyết bài toán sinh các dãy tam phân bằng cách thay range(0,2) bởi range(0,3). Kết quả thu được như sau:

    000
    001
    002
    010
    011
    012
    020
    021
    022
    100
    101
    102
    110
    111
    112
    120
    121
    122
    200
    201
    202
    210
    211
    212
    220
    221
    222

     

  • Linear regression machine learning with Excel

    Linear regression machine learning with Excel

    Linear regression machine learning with Excel

    Linear regression is a simple machine learning algorithm that has many uses for analyzing data and predicting outcomes. Linear regression is especially useful when your data is neatly arranged in tabular format. Excel has several features that enable you to create regression models from tabular data in your spreadsheets.

    1. What is a linear regression?

    As the name implies, linear regression is an approach to modeling the relationship between a dependent variable $y$ and one or more independent variables denoted as $x$ in a linear form. Linear means that the dependent variable is directly proportional to the independent variables. Keeping other things constant if $x$ is increased/decreased then $y$ also changes linearly. Mathematically the relationship is expressed in the simplest form as: $$y=Ax+B$$

    Here $A$ and $B$ are constant factors. The goal in supervised learning using linear regression is finding the value of constants  $A$ and $B$ using the data sets. Then we can use it to predict the values of $y$ in the future for any values of  $x$. Now, the cases where we have a single independent variable is called simple linear regression, while if there is more than one independent variable, then the process is called multiple linear regression.

    Quick facts about Linear Regression

    It’s a basic and commonly used type of predictive analysis. Three major uses for regression analysis are:
    1. Determining the strength of predictors
    2. Forecasting an effect
    3. Trend Forecasting

    There are several types of linear regression analyses available to researchers.

    • Simple linear regression
    • Multiple linear regression
    • Logistic regression
    • Ordinal regression
    • Multinominal regression
    • Discriminant analysis

    2. Application of Linear Regression

    Linear regression was the first type of regression analysis to be studied rigorously, and to be used extensively in practical applications. This is because models which depend linearly on their unknown parameters are easier to fit than models which are non-linearly related to their parameters and because the statistical properties of the resulting estimators are easier to determine. Linear regression can be applied to many situations. Most of the applications fall into one of the following two broad categories:

    • Prediction: In prediction or forecasting, linear regression can be first used to fit a predictive model to an observed data set of $y$ and $x$ values. After developing such a model, the fitted model can be used to make a prediction of the value of $y$ for an additional value of $x$.
      For example: If we have a dataset of rainfall amounts and corresponding temperatures, then we can fit a linear model and use it to predict the amount of rainfall for a temperature value whose rainfall amount is not known beforehand.
    • Finding strength of relationship: Given a variable $y$ and a number of independent variables $x_1, …, x_p$ that may be related to $y$, linear regression analysis can be used to quantify the strength of the relationship between $y$ and the $x_j$, to assess which $x_j$ may have no relationship with $y$ at all, and to identify which subsets of the $x_j$ contain redundant information about $y$.
      For example: If we have a dataset of rainfall amounts and corresponding humidity and temperatures, then we can use regression analysis to find out how strongly does the amount of rainfall depends upon each of these factors.

    To estimate the parameters of the linear regression model various techniques can be used. The most common ones are Least Squares (LS) method and maximum-likelihood estimation methods. Let’s discuss here an example of simple linear regression using ordinary least squares method.

    Least squares estimation:

    How do we go about picking or finding the parameters of the model? One way is to make the predicted value of $y$ as close to the actual value of the training set. For example: Suppose we have a training data $(x_{data}, y_{data})$. Then the reasonable thing to do would be to make the predicted value $y$ as close to $y_data$ as possible. Therefore we try to minimize the sum of the square of the error i.e $$S = S_j (y_{{data}_j} – y_­­­­j)^2$$

    For the simple case of a single independent variable after solving we obtain the following formulas for $A_0$ and $A_1$. $$A_{0}=\frac{n \sum_{i=1}^{n} y_{i} * x_{i}-\sum_{i=1}^{n} y_{i} * \sum_{i=1}^{n} x_{i}}{\sum_{i=1}^{n}\left(x_{i}-\text {mean}\right)^{2}}$$

    $$A_{1}=y-A_{0} * \text {mean}
    $$

    3. Linear regression machine learning with Excel

    https://www.youtube.com/watch?v=p4YgDMRV8aI&feature=youtu.be

    Let’s look at an example: The data in the table below shows the temperature during the race and the corresponding average finish time in minutes of a marathon.

    Linear regression machine learning with Excel 9

    From the scatter plot we can see that the relationship between the $x$ & $y$ is somewhat linear. Using the formula we get the values of the parameters, $A_0 = 0.688 , A_1= 191.83$.

    How do we make Prediction?

    Prediction for a new test value of x is done simply by putting the value in the equation for the linear regression model. We now have the parameters of the simple linear regression model: $$y = 0.688x + 191.83$$

    We can use it to predict the average completion time for different temperatures. For example, when the temperature is 71 F our model predicts the average completion time to be, $$y = 0.688*71 + 191.83 = 240.68 minutes.$$

    Linear Regression Chart

    Linear regression machine learning using data visualization feature in Excel

    One of the most intuitive is the data chart tool, which is a powerful data visualization feature. For instance, the scatter plot chart displays the values of your data on a cartesian plane. But in addition to showing the distribution of your data, Excel’s chart tool can create a machine learning model that can predict the changes in the values of your data. The feature, called Trendline, creates a regression model from your data. You can set the trendline to one of several regression algorithms, including linear, polynomial, logarithmic, and exponential. You can also configure the chart to display the parameters of your machine learning model, which you can use to predict the outcome of new observations.

    You can add several trendlines to the same chart. This makes it easy to quickly test and compare the performance of different machine learning models on your data.

    excel data science trendline

    Above: Excel’s Trendline feature can create regression models from your data.

    In addition to exploring the chart tool, Learn Data Mining Through Excel takes you through several other procedures that can help develop more advanced regression models. These include formulas such as LINEST and LINREG, which calculate the parameters of your machine learning models based on your training data.

    While this might not be the most efficient way to do production-level data science work, it is certainly a very good way to learn the workings of machine learning algorithms.

    https://www.newtechdojo.com/learn-linear-regression-using-excel/

    https://venturebeat.com/2020/12/30/you-dont-code-do-machine-learning-straight-from-microsoft-excel/

  • Cách chuyển PDF sang ảnh miễn phí

    Cách chuyển PDF sang ảnh miễn phí

    Cách chuyển PDF sang ảnh miễn phí

    Xem thêm VietOCR – Phần mềm nhận dạng văn bản tiếng Việt

    1. Cách chuyển PDF sang ảnh bằng phần mềm chụp ảnh màn hình

    Bước 1. Bạn mở tệp PDF bằng các phần mềm đọc PDF như Adobe Reader, Foxit Reader hoặc mở trực tiếp trên trình duyệt web (Chrome, Edge, Cốc cốc…)

    Bước 2. Sử dụng các các chụp ảnh màn hình thông dụng sau:

    • Sử dụng phím Print Screen
    • Sử dụng phần mềm Snipping Tool hoặc Snip & Sketch có sẵn của Windows
    • Sử dụng phần mềm chụp ảnh màn hình chuyên dụng như Snagit

    phan mem chup anh man hinh giúp chuyển file PDF sang hình ảnh

    Chi tiết hướng dẫn, xin mời bạn xem trong video sau

    2. Cách chuyển PDF sang ảnh bằng phần mềm đọc PDF

    Bước 1. Bạn mở tệp PDF cần chuyển sang hình ảnh bằng các phần mềm đọc PDF như Adobe Reader, Foxit Reader…

    Bước 2. Tất cả các phần mềm này đều có sẵn một công cụ sao chụp (copy màn hình) hiện tại vào clipboard và dán vào các phần mềm soạn thảo văn bản (MS Word, Libre Office…), các phần mềm chỉnh sửa ảnh (Paint, Photoshop,…) hoặc dán trực tiếp lên facebook,… Đó chính là Snapshot.

    tinh nang snapshot giúp chuyển file PDF sang file hình ảnh JPG

    Bước 3. Sau khi chọn (click vào nút Snapshot, hoặc dùng phím tắt Alt+7) bạn dùng chuột quét (nhấn giữ và kéo thả) khu vực cần chụp màn hình. Vùng được chọn sẽ được sao chép vào bộ nhớ tạm Clipboard.

    Bước 4. Bạn mở phần mềm soạn thảo văn bản, phần mềm chỉnh sửa ảnh và dán hình ảnh đang lưu trong Clipboard vào để biên tập tiếp, sử dụng phím tắt Ctrl+V hoặc bấm chuột phải và chọn Paste.

    Lưu ý, một số phần mềm như Foxit Phantom có cho phép chuyển nhiều trang PDF sang hình ảnh cùng một lúc, bạn chọn Tab Convert và chọn To Image như trong hình dưới đây. Sau đó chọn các trang PDF cần chuyển sang hình ảnh và lựa chọn định dạng cho hình ảnh cần lưu lại (JPG, PNG…)

    convert PDF to image

    3. Cách chuyển PDF sang ảnh trên điện thoại

    Trên điện thoại, bạn dùng app chuyển PDF sang ảnh X2IMG, phần mềm  Conver PDF to JPG (XPS, EPUB, CBZ to JPG)

    Bước 1. Bạn truy cập địa chỉ sau hoặc vào CH Play tìm phần mềm X2IMG và tiến hành cài đặt.

    👉Link tải app X2IMG bản miễn phí https://play.google.com/store/apps/details?id=com.pdftool.image&hl=en&gl=US

    cách chuyển pdf sang ảnh trên điện thoại

    Bước 2. Bạn mở app X2IMG và mở một tệp PDF cần chuyển sang ảnh (JPG, BMP, PNG,…) bằng cách bấm vào dấu + màu đỏ ở góc dưới bên phải của app.

    Bước 3. Lựa chọn

    • Convert to image (JPG) nếu muốn chuyển tất cả các trang của tài liệu PDF sang ảnh.
    • Select pages to convert (JPG) nếu muốn chọn các trang cụ thể của tài liệu PDF và chuyển sang hình ảnh.

    Bước 4. Sau khi app X2IMG chuyển đổi các trang PDF sang hình ảnh (JPG), chúng được lưu trên bộ nhớ của máy và có thể xem trong các app xem ảnh, hoặc lựa chọn chúng và chia sẻ (up lên fb, chia sẻ qua zalo…)

    4. Cách chuyển PDF sang ảnh online

    Bạn sử dụng các dịch vụ chuyển PDF sang hình ảnh online như pdftoimage.com, smallpdf.com, pdfcandy.com

  • Macbook Air lập trình được không?

    Macbook Air lập trình được không?

    Macbook Air lập trình được không là câu hỏi mà nhiều người dùng băn khoăn khi muốn chuyển sang dòng máy tính xách tay của Apple (Macbook, Mac Pro, Mac Mini).

    Xem thêm Giáo viên có nên dùng Macbook không?

    Giáo viên có nên dùng Macbook?

    Câu trả lời là, nếu bạn chỉ lập trình nhẹ nhàng kiểu tác vụ văn phòng như soạn thảo văn bản Word, Powerpoint, làm web (PHP, Javascrip, HTML và CSS,..), lướt web, xem Youtube… thì Macbook Air là sự lựa chọn tốt nhất với các ưu điểm dưới đây. Còn nếu bạn lập trình mobile, làm đồ họa, làm video… thì Macbook Air không đáp ứng được nhu cầu đó, chúng tôi khuyên bạn nên mua các dòng Macbook Pro đời từ 2017 trở lên.

    Update: Hiện tại, với phiên bản chip M1 thì Macbook Air hoàn toàn có thể đáp ứng tốt hầu hết các nhu cầu lập trình, biên tập video (video editor). Cá nhân tôi đang dùng bản Air M1 RAM 16G SSD 512G và thấy hoàn toàn hài lòng, kể cả lập trình Flutter hoặc sử dụng XCode. Chúng tôi khuyên bạn nên lựa chọn phiên bản có RAM 16G và bộ nhớ 512G. Nếu bắt buộc phải cắt giảm chi phí thì có thể lấy phiên Macbook Air 16Gb 256Gb.

    Ưu điểm của Macbook/Macbook Air cho lập trình

    1. Mỏng Nhẹ. Tính năng này rất quan trọng khi mà bạn phải di chuyển thường xuyên. Lập trình không có nghĩa là cứ ngồi một chỗ code, ví du: đi từ nhà đến trường (rồi có thể đi đến trung tâm bên ngoài để học thêm), học nhóm, hội thảo, meetup, hackathon…
    2. Pin Trâu. Thời gian xài pin trung bình của Macbook Air là khoảng 10 tiếng. Đặc biệt là các dòng Macbook Air M1 sử dụng chip của Apple ra mắt cuối năm 2020 có thời lượng pin khủng khiếp (18 – 20 tiếng).
    3. Môi trường lập trình cực kỳ tốt. Đặc biệt nếu bạn muốn phát triển app cho iPhone, iPad, Macbook thì chỉ có thể sử dụng máy tính chạy hệ điều hành của Apple mà thôi (chi tiết vấn đề này xin xem phần sau).
    4. Đẹp. Đây là điều khó có thể chối cãi. Macbook luôn là sản phẩm có độ hoàn thiện và tính thẩm mĩ cao, là niềm ao ước không chỉ của dân văn phòng mà còn của các lập trình viên.

    Macbook phù hợp nhiều hệ điều hành

    • Macbook có thể phát triển phần mềm cho bất kỳ hệ điều hành nào. Trong khi bất kỳ một chiếc PC nào cũng có thể dùng để phát triển App cho Windows, Linux và Android. Thì duy nhất máy Mac có thể tương thích các ứng dụng MacOs và iOS. Ưu thế hệ điều hành hoàn hảo cho giới phát triển vaà các nhà xây dựng ứng dụng di động iOS cũng trở thành sợi dây trói vô số nhà phát triển đến với trải nghiệm PC của Apple.
    • Xét về khía cạnh công cụ Code thì MacOs cũng có thể coi là vượt trội hơn cả. Do là một hệ điều hành nhân Unix, MacOs có sở hữu sự mạnh mẽ và vượt trội hơn hẳn so với Windows hay nhiều công cụ cần thiết được cài đặt sẵn. Nhìn về tổng thể thì các bộ công cụ cần thiết. Trên MacOs không thua kém mà thậm chí vượt trội so với hệ điều hành của Microsoft. Nếu nói về hiệu năng hoạt động của các IDE. Hay các Tools cần thiết khác Windows quả thật không phải là đối thủ của Macos.

    Macbook Air lập trình được không?

    Tốt nhất là nên chọn Macbook Pro (cho dù là Macbook Pro 2015 thì vẫn có hiệu năng tốt hơn cả Macbook Air 2017), bởi nó luôn được trang bị những gì đẳng cấp nhất. Còn nếu ít tiền thì có thể lựa chọn Macbook Air hoặc The New Macbook, tuy cấu hình không bằng Macbook Pro nhưng nếu so sánh với mấy con Dell Vostro hay các dòng máy chạy window tầm giá 10 – 15 triệu thì vẫn hơn đứt.

    Các dòng Macbook thấp hơn 2015 thì thôi không nên mua vì nó cũng khá lâu rồi, nên bạn hãy chọn đời máy từ 2015 trở lên sẽ tốt hơn.

    Cả 2 dòng Macbook Air và Macbook Pro từ năm 2015 tới năm 2019 đều có cấu hình khá tương đồng, Apple họ cứ tung hô phiên bản sau nâng cấp này nâng cấp nọ nhưng thực tế trải nghiệm thì mấy không thay đổi gì, phiên bản 2015 vẫn chạy bon không kém 2019.

    Có điều bạn phải lưu ý tới việc Apple đã loại bỏ cổng kết nối USB kể từ Macbook Air 2018 và Macbook Pro 2016. Nếu lựa chọn phải dòng này, bạn phải mua thêm bộ chuyển cổng kết nối (khoảng 2 triệu đối với hàng chính hãng Apple).

    Vậy tối ưu nhất cho developer là dòng máy Macbook Pro 2015 trở lên.

    Macbook Pro 13 inch hay Macbook Pro 15 inch?

    Nếu bạn chọn Macbook Pro thì lại có 2 lựa chọn là 13 inch và 15 inch. Macbook Pro 15 inch dành cho những bạn phải thường xuyên xử lý tác vụ nặng như build app mobile, render video. Còn nếu bạn là web developer thì chỉ cần 13 inch là đủ.