Home Blog Page 107

Hướng dẫn cài đặt, lập trình Python trên Ubuntu (Linux)

Hướng dẫn cài đặt, lập trình Python trên Ubuntu (Linux).

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Hướng dẫn cài đặt, lập trình Python trên Ubuntu (Linux).

Cài Python qua repository

Đây là cách đơn giản nhất, các bạn không cần phải lên trang chủ python để tải file, giải nén…

Chỉ cần chạy lệnh là được.

B1: Update lại repository

sudo apt-get update

B2: Cài python

sudo apt-get install python

Mặc định nó sẽ cài cho bạn 2 bản python là 2.x và 3.x

Để kiểm tra version của python sau khi cài đặt các bạn dùng lệnh sau:

Với python 2.x: python hoặc python -V

Hướng dẫn cài đặt, lập trình Python trên Ubuntu (Linux)

Với python 3.x: python3 hoặc python3 -V

Hướng dẫn cài đặt, lập trình Python trên Ubuntu (Linux)

  Học Python: Từ Zero đến Hero (phần 1)

Demo:

Chạy lệnh python và nhập print('hello') sau đó ấn enter sẽ thấy nó in ra dòng hello

Hướng dẫn cài đặt, lập trình Python trên Ubuntu (Linux)

  Chuyển đổi hệ cơ số trong Python

Cài đặt pip cho python

pip (python package manager) là một trình quản lý module, thư viện của python.

Ví dụ bạn muốn thực hiện kết nối tới database bằng python thì bạn phải có module mysqlclient (trong java thì là thư viện jdbc). Nhưng khi cài python nó chưa có sẵn module đó, để cài module mysqlclient ta cài qua pip bằng lệnh pip install mysqlclient

Thông thường các bản python mới sẽ tích hợp sẵn pip. Để kiểm tra pip đã cài chưa, các bạn dùng lệnh pip –version với python 2.x hoặc pip3 –version với python 3.x

Hướng dẫn cài đặt, lập trình Python trên Ubuntu (Linux)

Trường hợp python của bạn chưa tích hợp sẵn pip thì bạn có thể cài đặt pip bằng lệnh sau:

sudo apt-get install pip

hoặc

sudo apt-get install pip3

References:

https://docs.python.org/3/

Bài viết gốc được đăng tải tại codecute.com

Có thể bạn quan tâm:

Xem thêm việc làm developer hấp dẫn trên TopDev

Cho phép tùy chọn Giao diện trong Spring Web MVC framework

Cho phép tùy chọn Giao diện trong Spring Web MVC framework

Bài viết được sự cho phép của tác giả Trần Thị Thu Hà

Để tăng độ hài lòng của khách truy cập, trang web có thêm tùy chọn Giao diện theo ý muốn của người dùng. Trong bài viết này, chúng mình sẽ chia sẻ với bạn cách xây dựng một ứng dụng Spring Web MVC như thế.

  Giải thích mô hình MVC thông qua … cốc trà đá
  Google AMP là gì ? Cài đặt AMP cho website asp.net mvc

Bạn cần khởi tạo project bằng Maven archetype có tên maven-archetype-webapp, nếu bạn chưa rõ cách khởi tạo hãy xem bài viết Kỹ thuật Autowiring sử dụng annotation trong Spring Framework. Cấu trúc thư mục của ứng dụng sẽ như sau:

Cho phép tùy chọn Giao diện trong Spring Web MVC framework

Chúng ta sẽ tạo 14 files mã nguồn bao gồm:

  1. JobController.java
  2. Job.java
  3. beach.properties
  4. classic.properties
  5. modern.properties
  6. beach.css
  7. classic.css
  8. modern.css
  9. addjob.jsp
  10. resultJob.jsp
  11. springmvc-servlet.xml
  12. web.xml
  13. index.jsp
  14. pom.xml

Sau khi Maven tự động tạo cho bạn một số thư mục có sẵn, bạn cần tạo thêm thư mục java, css, pages như trong ảnh chụp màn hình. Sửa lại file pom.xml có nội dung như sau:

Ứng dụng Spring Web MVC cần tối thiểu các dependencies là: spring-core, spring-beans, spring-context, spring-web, spring-webmvc. Chúng ta bổ sung thêm thư viện JUnit để sau này viết Unit test, bổ sung thêm hibernate-validator để validate dữ liệu nhập vào qua form. Tất cả các dependency đều được khai báo 3 tham số GAV (GroupId – ArtifactId – Version). Khi khao báo version cho dependency, chúng ta sử dụng cách tổng quát hóa, khai báo số phiên bản qua properties trong pom.xml, đây là best practice, giả sử khi Spring Framework phát hành phiên bản 4.3.0.RELEASE, thì chúng ta chỉ cần thay đổi giá trị phiên bản này trong 1 vị trí chứ không phải 5 vị trí:

Là một ứng dụng web, nên trước khi xây dựng ứng dụng, bạn cần để ý đến file web.xml (deployment descriptor file). Từ dòng 7 – 18 là nội dung filter, filter này đảm bảo cho việc truyền dữ liệu ký tự Unicode tiếng Việt được đúng. Nếu bỏ qua thiết lập này, ứng dụng của bạn sẽ bị lỗi Font tiếng Việt. Filter có tên encodingFilter  này tác động đến tất cả các đường dẫn ứng dụng (được mô tả bằng <urlpatter>/*</urlpattern> ). Dòng 26 và 31 là đặc biệt quan trọng, để Spring Web MVC xử lý luồng đi của ứng dụng web.

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/webapp_3_1.xsd"
version="3.1">

<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.mvc</url-pattern>
</servlet-mapping>

</web-app>

Tạo thực thể Job (công việc). Các quy tắc kiểm tra tính hợp lệ dữ liệu đầu vào được thiết lập bằng annotation: @Size, @NotNull. Hibernate Validator phụ trách việc này.Một công việc có 8 thuộc tính là:

  1. title: Tiêu đề công việc
  2. company: Công ty tuyển dụng
  3. companyAddress: Địa chỉ công ty, nơi làm việc
  4. content: Chi tiết về yêu cầu tuyển dụng, chế độ đãi ngộ, thời gian làm việc, v.v..
  5. startDate: Ngày đăng tin
  6. endDate: Ngày gỡ tin tuyển dụng
  7. salary: Tiền lương
  8. createDate: Thời điểm tạo bản tin tuyển dụng

Controller:

package vn.smartjob.demospring.controller;

import vn.smartjob.demospring.domain.Job;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class JobController {

@RequestMapping(value = "/form")
public ModelAndView job() {
return new ModelAndView("addJob", "job", new Job());
}

@RequestMapping(value = "/result", method = RequestMethod.POST)
public ModelAndView processJob(Job job, BindingResult result) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("j", job);
if (result.hasErrors()) {
modelAndView.setViewName("addJob");
} else {
modelAndView.setViewName("resultJob");
}
return modelAndView;
}

}

Cấu hình bean cho Spring Framework. Nghiệp vụ tùy chọn giao diện (theme) của người dùng được xử lý ở dòng thứ 24-26.

Class  org.springframework.web.servlet.theme.ThemeChangeInterceptor chịu trách nhiệm về việc này. Giao diện (theme) mặc định là modern (Hiện đại), là giao diện xuất hiện khi người dùng chưa đưa ra tùy chọn riêng cho mình.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

<context:component-scan base-package="vn.smartjob.demospring"/>
<context:annotation-config/>
<mvc:annotation-driven/>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>

<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource"/>

<bean id="themeResolver" class="org.springframework.web.servlet.theme.SessionThemeResolver">
<property name="defaultThemeName" value="modern"/>
</bean>

<mvc:interceptors>
<bean id="themeChangeInterceptor" class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
<property name="paramName" value="theme"/>
</bean>
</mvc:interceptors>

</beans>


Chúng ta sẽ tạo 3 giao diện có tên là:

  • Classic: Cổ điển
  • Modern: Hiện đại
  • Beach: Bờ biển

3 tập tin css tương ứng là:

File classic.css

body {
background-color: #ffcab3;
color: #ffe48e;
}

.error {
background-color: gainsboro;
}
table{
width: 600px;
background-color: #2898ff;
}
td{
width: 300px;
}

File modern.css

body {
background-color: white;
color: black;
}

.error {
background-color: lime;
}
table{
width: 600px;
background-color: darkcyan;
}
td{
width: 300px;
}

File beach.css

body {
background-color: #28e2ff;
color: green;
}

.error {
background-color: beige;
}
table{
width: 600px;
background-color: lightblue;
}
td{
width: 300px;
}

Tạo 3 tập tin *.properties nằm trong thư mục resources:

File classic.properties

File modern.properties

File beach.properties

Cần 2 trang JSP, một trang để thêm công việc mới và một trang để hiển thị kết quả:

Trang thêm mới công việc addJob.jsp . Bạn phải nhớ khai báo thư viện tag sử dụng như ở dòng 2 và dòng 3. Hãy để ý vào dòng 8, 13 và 14. Khi người dùng bấm chọn Giao diện, thì đường dẫn đến file css giao diện thay đổi, được xử lý bởi tag <spring> .

<%@ page contentType="text/html;charset=UTF-8" %>
<%@taglib prefix="mvc" uri="http://www.springframework.org/tags/form" %>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<html>
<head>
<title>Thêm công việc mới</title>
<link rel="stylesheet" href="<spring:theme code="style"/>" type="text/css"/>
</head>
<body>

<h2>Thêm công việc mới</h2>
Giao diện: <a href="?theme=classic">Cổ điển</a> - <a href="?theme=modern">Hiện đại</a> - <a href="?theme=beach">Bờ
biển</a><br/>

<mvc:form modelAttribute="job" action="result.mvc">
<table>
<tr>
<td><mvc:label path="title">Tiêu đề công việc</mvc:label></td>
<td><mvc:input path="title" cssErrorClass="error"/></td>
<td><mvc:errors path="title"/></td>
</tr>
<tr>
<td><mvc:label path="company">Công ty</mvc:label></td>
<td><mvc:input path="company" cssErrorClass="error"/></td>
<td><mvc:errors path="company"/></td>
</tr>
<tr>
<td><mvc:label path="companyAddress">Địa chỉ làm việc</mvc:label></td>
<td><mvc:input path="companyAddress" cssErrorClass="error"/></td>
<td><mvc:errors path="companyAddress"/></td>
<td></td>
</tr>
<tr>
<td><mvc:label path="content">Nội dung tuyển dụng</mvc:label></td>
<td><mvc:textarea path="content" cssErrorClass="error"/></td>
<td><mvc:errors path="content"/></td>
</tr>
<tr>
<td><mvc:label path="salary">Mức lương</mvc:label></td>
<td><mvc:input path="salary" cssErrorClass="error"/></td>
<td><mvc:errors path="salary"/></td>
</tr>
<tr>
<td><mvc:label path="startDate">Ngày bắt đầu đăng tin (mm/dd/yyyy)</mvc:label></td>
<td><mvc:input path="startDate" cssErrorClass="error"/></td>
<td><mvc:errors path="startDate"/></td>
</tr>
<tr>
<td><mvc:label path="endDate">Ngày gỡ bỏ tin (mm/dd/yyyy)</mvc:label></td>
<td><mvc:input path="endDate" cssErrorClass="error"/></td>
<td><mvc:errors path="endDate"/></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Gửi">
</td>
</tr>
</table>
</mvc:form>

</body>
</html>

Trang hiển thị kết quả resultJob.jsp

Trang chủ index.jsp sẽ trỏ về trang thêm mới công việc

Đến nay chúng ta đã tạo đủ 14 file và project đã hoàn tất, chạy ứng dụng trên Apache Tomcat để thấy kết quả:

Giao diện mặc định là Hiện đại (Modern) được thiết lập ở dòng 25 trong file springmvc-servlet.xml

Cho phép tùy chọn Giao diện trong Spring Web MVC framework

Bấm chọn và đổi giao diện, ta có giao diện Cổ điển (classic):

Giao diện Bờ biển (beach):

Cho phép tùy chọn Giao diện trong Spring Web MVC framework

Sau khi bấm nút Gửi, nếu dữ liệu hợp lệ, sẽ trả về trang kết quả:

Cho phép tùy chọn Giao diện trong Spring Web MVC framework

(Nội dung xuất hiện trong tất cả ảnh chụp màn hình chỉ mang tính chất minh họa)

Tải về mã nguồn từ server SmartJob: theme hoặc GitHub: https://github.com/SmartJobVN/spring_theme

Đỗ Như Vý – Bài viết gốc được đăng tải tại smartjob.vn

Có thể bạn quan tâm:

Xem thêm Jobs Developer hấp dẫn trên TopDev

Bảng băm trong C++

https://topdev.vn/blog/system-design-co-ban-consistent-hashing/

Bài viết được sự cho phép của tác giả Khiêm Lê

Bảng băm là gì?

Bảng băm hay HashTable là một cấu trúc mà khi người dùng thực hiện truy xuất một phần tử qua khóa thì nó sẽ được ánh xạ vào thông qua hàm băm (Hash function).

  1001 Tips: Con trỏ và hàm (Pointer & Function) trong C++
  C Token là gì? Cú pháp trong lập trình C/C++

Quá trình ánh xạ khóa vào bảng băm được thực hiện thông qua hàm băm (Hashing). Một bảng băm tốt cần phải có hàm băm tốt. Bảng băm là một mảng có M vị trí được đánh số từ 0 đến M – 1.

Bảng băm

Có rất nhiều cách cài đặt kết nối của bảng băm như trực tiếp, dò tuyến tính, dò bậc hai, băm kép… Trong bài viết này mình sẽ giới thiệu đến các bạn phương pháp kết nối dò trực tiếp. Nhưng trước tiên, ta cần tìm hiểu hàm băm trước đã vì như mình đã nói, một bảng băm tốt khi nó có hàm băm tốt.

Trước khi vào bài, phương pháp kết nối trực tiếp là phương pháp sử dụng danh sách liên kết đơn, do đó, bạn nào chưa biết gì về danh sách liên kết đơn thì hãy xem lại bài Danh sách liên kết đơn trong C++ để hiểu rõ hơn nha.

Hàm băm

Hàm băm hay là Hash function là hàm thực hiện việc ánh xạ khóa k nào đó vào trong bảng băm (h(k)). Một hàm băm tốt thỏa mản các tiêu chí sau:

  • Tốc độ tính toán nhanh
  • Các khóa được phân bố đều trong bảng
  • Ít xảy ra đụng độ

Mình sẽ giới thiệu đến các bạn các phép băm thường được sử dụng nhất là phương pháp chia và nhân.

Đối với phương pháp chia, mình sẽ ánh xạ khóa theo hàm h(k) = k % M, với k là khóa và M là kích thước của bảng băm.

Đối với phương pháp nhân, hàm ánh xạ h(k) = M * (k*A % 1), với k là khóa, M là kích thước bảng băm và A là số thực 0 < A < 1. Theo phương pháp nhân này, sự hiệu quả phụ thuộc vào việc lựa chọn A, theo như nhà khoa học máy tính Knuth, chọn A = (sqrt(5) – 1) / 2 là hiệu quả nhất (xấp xỉ 0.618033987).

Thông thường, mình sử dụng phương pháp chia cho dễ cài đặt. Tuy nhiên, không thể nào tránh khỏi đụng độ dù có dùng hàm băm nào đi nữa, do đó, chúng ta cần giải quyết đụng độ.

Giải quyết đụng độ

Đối với việc sử dụng phương pháp kết nối trực tiếp, các phần tử bị đụng độ sẽ được thêm vào danh sách liên kết tại h(k) trong bảng băm.

Giải quyết đụng độ bảng băm

Như bạn có thể thấy trong hình, các khóa như 7, 17 đụng độ nhau thì chúng sẽ được thêm vào danh sách liên kết ở h(k) = M. Tương tự các khóa 4, 19 cũng bị đụng và được thêm vào danh sách liên kết ở h(k) = 2…

Bây giờ chúng ta hãy cùng bắt đầu cài đặt bảng băm vào trong trong C++ nha.

Cấu trúc một nút trong bảng băm

Như đã nói, phương pháp kết nối trực tiếp dùng danh sách liên kết đơn, các phần tử bị đụng độ tại phần tử i trong bảng băm thì sẽ được thêm vào danh sách liên kết đơn tại i trong bảng băm. Do đó, một phần tử trong bảng băm có cấu trúc như một nút trong danh sách liên kết đơn.

struct Node
{
    int key;
    Node* next;
};

Cấu trúc bảng băm và hàm khởi tạo

Một bảng băm là một mảng chứa các nút, giả sử mình có 100 phần tử, vậy mình sẽ định nghĩa một HashTable như sau:

#define M 100

typedef Node *HashTable[M];

Như vậy, chúng ta có thể khai báo một bảng băm như sau:

HashTable mHashTable;

Các bạn có thể dễ dàng thấy một nút trong bảng là một con trỏ trỏ đến một Node, như vậy, chúng ta cần phải khởi tạo chúng bằng NULL để tránh gặp lỗi. Mình sẽ có hàm khởi tạo bảng như sau:

void InitHashTable(HashTable &HT)
{
    for (int i = 0; i < M; i++)
        HT[i] = NULL;
}

Hàm băm

Như đã nói ở trên, để đơn giản mình sẽ sử dụng hàm băm theo phép chia:

int Hash(int k)
{
    return k % M;
}

Thêm một nút vào bảng băm

Để thêm một nút, ta cần xác định vị trí sẽ thêm qua hàm băm h(k), sau đó thêm vào danh sách liên kết ở vị trí h(k) đó. Việc đụng độ sẽ được giải quyết do nếu đụng độ thì khóa sẽ được tự thêm vào sau danh sách liên kết đơn. Mình sẽ có hàm thêm như sau:

void InsertNode(HashTable &HT, int k)
{
    int i = Hash(k);
    AddTail(HT[i], k);
}

Hàm AddTail thì trong danh sách liên kết đơn, mình đã có bài viết về nó rồi, các bạn có thể đọc lại.

void AddTail(Node *&l, int k)
{
    Node *newNode = new Node{k, NULL};
    if (l == NULL)
    {
        l = newNode;
    }
    else
    {
        Node* p = l;
        while (p != NULL && p->next != NULL)
            p = p->next;
        p->next = newNode;
    }
}

Tìm kiếm một khóa trong bảng băm

Để tìm kiếm một khóa trong bảng băm, ta cũng thực hiện xác định vị trí h(k), sau đó ta thực hiện tìm kiếm trong danh sách liên kết tại vị trí h(k) trong bảng băm.

Node *SearchNode(HashTable HT, int k)
{
    int i = Hash(k);
    Node *p = HT[i];
    while (p != NULL && p->key != k)
        p = p->next;
    if (p == NULL)
        return NULL;
    return p;
}

Xóa một nút ra khỏi bảng băm

Để xóa một phần tử ra khỏi bảng băm, đầu tiên ta cũng phải xác định h(k), sau đó tìm xem nó nằm ở đâu trong danh sách liên kết đơn tại vị trí h(k) đó rồi thực hiện xóa nó đi.

void DeleteNode(HashTable &HT, int k)
{
    int i = Hash(k);
    Node *p = HT[i];
    Node *q = p;
    while (p != NULL && p->key != k)
    {
        q = p; // Lưu lại địa chỉ của phần tử trước đó
        p = p->next;
    }
    if (p == NULL)
        cout << k << " not found!" << endl;
    else if (p == HT[i])
        DeleteHead(HT[i]); // Nút cần xóa là phần tử đầu của DSLK
    else
        DeleteAfter(q); // Xóa nút sau nút q
}

Hai hàm DeleteHead và DeleteAfter cũng đã được mình trình bày trong bài Danh sách liên kết đơn trong C++ rồi nên mình sẽ không giả thích gì thêm.

void DeleteHead(Node *&l)
{
    if (l != NULL)
    {
        Node *p = l;
        l = l->next;
        delete p;
    }
}

void DeleteAfter(Node *&q)
{
    Node *p = q->next;
    if (p != NULL)
    {
        q->next = p->next;
        delete p;
    }
}

Duyệt qua bảng băm

Duyệt qua bảng băm rất đơn giản, bạn chỉ cần duyệt qua mảng, mỗi phần tử của mảng là một danh sách liên kết đơn, vậy thì duyệt danh sách liên kết đơn nữa là xong.

void Traverse(Node *p) // duyệt DSLK
{
    while (p != NULL)
    {
        cout << p->key << ' ';
        p = p->next;
    }
    cout << endl;
}

void TraverseHashTable(HashTable HT)
{
    for (int i = 0; i < M; i++)
    {
        cout << "Bucket " << i << ": ";
        Traverse(HT[i]);
    }
}

Lưu ý về bảng băm

Đối với dữ liệu lớn, việc cấp phát một mảng quá lớn sẽ gây lãng phí bộ nhớ không đáng có, tuy nhiên, việc M lớn đảm bảo việc đụng độ ít xảy ra do các khóa phân bố đều. Ngược lại, nếu M nhỏ để tiết kiệm bộ nhớ, việc này sẽ làm giảm hiệu suất của bảng băm do việc đụng độ xảy ra với tần suất cao hơn.

Do vậy, khi thao tác với bảng băm, các bạn cần phải cân nhắc giữa hiệu suất và dung lượng lưu trữ.

Tổng kết

Như vậy là trong bài viết này, mình đã giới thiệu đến các bạn về bảng băm trong C++, cách cài đặt bảng băm bằng phương thức kết nối trực tiếp dùng danh sách liên kết đơn. Nếu các bạn có bất kỳ ý kiến, đóng góp nào, đừng ngần ngại comment phía bên dưới bài viết nha. Cảm ơn các bạn đã theo dõi bài viết!

Source code

#include <iostream>
using namespace std;

#define M 10

struct Node
{
    int key;
    Node *next;
};

typedef Node *HashTable[M];

void InitHashTable(HashTable &HT)
{
    for (int i = 0; i < M; i++)
        HT[i] = NULL;
}

int Hash(int k)
{
    return k % M;
}

void AddTail(Node *&l, int k)
{
    Node *newNode = new Node{k, NULL};
    if (l == NULL)
    {
        l = newNode;
    }
    else
    {
        Node* p = l;
        while (p != NULL && p->next != NULL)
            p = p->next;
        p->next = newNode;
    }
}

void InsertNode(HashTable &HT, int k)
{
    int i = Hash(k);
    AddTail(HT[i], k);
}

void DeleteHead(Node *&l)
{
    if (l != NULL)
    {
        Node *p = l;
        l = l->next;
        delete p;
    }
}

void DeleteAfter(Node *&q)
{
    Node *p = q->next;
    if (p != NULL)
    {
        q->next = p->next;
        delete p;
    }
}

void DeleteNode(HashTable &HT, int k)
{
    int i = Hash(k);
    Node *p = HT[i];
    Node *q = p;
    while (p != NULL && p->key != k)
    {
        q = p;
        p = p->next;
    }
    if (p == NULL)
        cout << k << " not found!" << endl;
    else if (p == HT[i])
        DeleteHead(HT[i]);
    else
        DeleteAfter(q);
}

Node *SearchNode(HashTable HT, int k)
{
    int i = Hash(k);
    Node *p = HT[i];
    while (p != NULL && p->key != k)
        p = p->next;
    if (p == NULL)
        return NULL;
    return p;
}

void Traverse(Node *p)
{
    while (p != NULL)
    {
        cout << p->key << ' ';
        p = p->next;
    }
    cout << endl;
}

void TraverseHashTable(HashTable HT)
{
    for (int i = 0; i < M; i++)
    {
        cout << "Bucket " << i << ": ";
        Traverse(HT[i]);
    }
}

int main()
{
    HashTable mHashTable;
    InitHashTable(mHashTable);

    InsertNode(mHashTable, 0);
    InsertNode(mHashTable, 1);
    InsertNode(mHashTable, 2);
    InsertNode(mHashTable, 3);
    InsertNode(mHashTable, 10);
    InsertNode(mHashTable, 13);
    InsertNode(mHashTable, 9);
    InsertNode(mHashTable, 11);

    cout << "HashTable:\n";
    TraverseHashTable(mHashTable);

    DeleteNode(mHashTable, 3);
    DeleteNode(mHashTable, 13);
    DeleteNode(mHashTable, 9);
    cout << "HashTable after Delete:\n";
    TraverseHashTable(mHashTable);

    Node *result = SearchNode(mHashTable, 10);
    if (result == NULL)
        cout << "Not found!";
    else
        cout << "Found!";

    std::cout << std::endl;
    system("pause");
    return 0;
}
Bài viết gốc được đăng tải tại khiemle.dev
Có thể bạn quan tâm:
Xem thêm TOP It jobs for Developer hấp dẫn trên TopDev

Quy trình 3 bước trong Machine Learning và hàm chi phí

Quy trình 3 bước trong Machine Learning và hàm chi phí

Bài viết được sự cho phép của tác giả Kien Dang Chung

Video trong bài viết

Trong Phần 1: Dự đoán doanh thu phim với Hồi quy tuyến tính, chúng ta đã được làm quen với Machine Learning và thuật toán Hồi quy tuyến tính (Linear Regression). Các bài học ở phần 1 mới chỉ mang tính chất giới thiệu, để bạn đọc có thể hiểu sơ lược xem Machine Learning là gì? khi áp dụng vào các bài toán thực tế nó đem lại kết quả ra sao?

  9 hiểu lầm "ngớ ngẩn" về machine learning
  Chia sẻ cơ bản sử dụng machine learning để giải quyết bài toán.

Quy trình 3 bước trong Machine Learning

Bạn có nhớ trong bài toán dự đoán doanh thu bằng Linear Regression chúng ta đã sử dụng thuật toán được cài đặt sẵn trong thư viện Scikit-learn. Nhưng chúng ta không đi sâu vào Machine learning diễn ra như thế nào?

Theo hoạt động học tập thông thường, chúng ta cần đưa dữ liệu vào máy tính và nó có thể trả lời các câu hỏi của chúng ta. Cách máy tính học là chúng nhìn ra các mối quan hệ trong dữ liệu. Quay lại với Linear Regression, chúng ta tìm hiểu xem máy đã học như thế nào?

Trước hết, chúng ta cùng đến với quy trình 3 bước trong Machine Learning và sau đó sẽ áp dụng vào một thuật toán cụ thể.

Quy trình 3 bước trong Machine Learning và hàm chi phí

  • Bước 1: Đưa ra dự đoán (đưa ra một giá trị bất kỳ đầu tiên).
  • Bước 2: Tính toán các sai lệch dựa trên dự đoán và dữ liệu đầu vào
  • Bước 3: Máy học, điều chỉnh dự đoán ban đầu và quay về với bước 1.

Phần tiếp theo có liên quan đến Phần 1: Dự đoán doanh thu phim với Linear Regression, bạn nên xem phần 1 trước khi bắt đầu bài viết này vì có rất nhiều thông tin liên quan.

Quay lại với bài toán dự đoán bằng Linear Regression, chương trình cần học và đưa ra các giá thị θ0θ0 và θ1θ1 tối ưu. Bước 1, nó sẽ dự đoán giá trị θ0θ0 và θ1θ1 ví dụ θ00θ00 và θ01θ10. Sau đó, tại bước 2, nó thực hiện tính toán sai lệch. Ở đây, trong thuật toán Linear Regression chúng ta sử dụng Tổng bình phương độ lệch để làm tiêu chí đánh giá xem dự đoán ở bước 1 là đã đúng hay chưa?

TngBìnhPhươngĐLch(RSS)=(y(1)hθ(x(1)))2+(y(2)hθ(x(2)))2+...+(y(n)hθ(x(n)))2=i=nn(y(i)hθ(x(i)))2TổngBìnhPhươngĐộLệch(RSS)=(y(1)−hθ(x(1)))2+(y(2)−hθ(x(2)))2+…+(y(n)−hθ(x(n)))2=∑i=nn(y(i)−hθ(x(i)))2

Với đường thẳng cần dự đoán là:

hθ(x)=θ0+θ1xhθ(x)=θ0+θ1x

Trong đó, θ0θ0 là điểm cắt với trục y, θ1θ1 là độ dốc của đường thẳng. x(i)x(i)y(i)y(i) là ngân sách và doanh thu của phim ii trong tập dữ liệu ban đầu.

Ở bước thứ 3, nó so sánh RSS của lần tính toán trước với lần tính toán này xem cái nào tốt hơn, nếu đã đủ tốt với một độ chính xác yêu cầu, máy tính dừng lại, nếu chưa nó điều chỉnh các giá trị dự đoán θ0θ0 và θ1θ1 và quay lại bước 1.

Chúng ta đã coi RSS là độ lớn sai lệch tính toán trong Linear Regression. Một phần rất rộng trong Machine Learning là tối ưu hóa để tìm ra các giá trị nhỏ nhất, ví dụ như ở bài toán trên chúng ta cần tìm RSS nhỏ nhất và như vậy với θ0θ0 và θ1θ1 có được, chúng ta có được đường thẳng nói lên mối quan hệ giữa ngân sách và doanh thu phim. Trong Machine learning các hàm này gọi là hàm chi phí (cost function) hoặc hàm mất mát (lost function).

Có thể bạn chưa thật sự hiểu về quy trình 3 bước trong machine learning này nhưng cũng đừng lo lắng, khi bắt đầu vào thiết kế thuật toán và viết code Python bạn sẽ hiểu thôi. Tôi đảm bảo đấy.

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm Tuyển dụng Machine Learning hấp dẫn trên TopDev

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ).

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Để thực hiện viết code Python trên intellij IDEA ta cần cài đặt plugin Python.

File/Setting (hoặc ấn tổ hợp phím Ctrl + Alt + S)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Chọn menu Plugins, và gõ python để tìm kiếm plugin Pytthon.

Hiện tại máy mình chưa cài plugin python nên mình sẽ cần search nó ở repositories.

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Chọn Plugin Python và Install.

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Sau khi cài đặt thành công thì khởi động lại IntelliJ để nó nhận plugin vừa cài đặt

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Như vậy là bạn đã cài đặt thành công plugin python để lập trình python trên IntelliJ.

  Selenium WebDriver trên Python

Ví dụ Python Hello World trên IntelliJ

Chọn File/New/Project

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Chọn Python. Phần Project SDK thì các bạn trỏ tới file python.exe trong folder python mà bạn đã cài đặt. (Ví dụ máy bạn cài cả bản python 3 và python 2 thì bạn có thể lựa chọn bản mà mình muốn)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Kết quả:

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

  Tổng hợp các Module Python "khủng" mà bạn có thể đã bỏ qua

Tạo file hello.py với nội dung print("hell world)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Chạy file hello.py trên bằng cách click chuột phải vào file hello.py và chọn Run (hoặc Ctrl+Shift+F10)

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Kết quả:

Lập trình Python trên IntelliJ IDEA (code Python trên IntelliJ)

Bài viết gốc được đăng tải tại codecute.com

Có thể bạn quan tâm:

Xem thêm Việc làm python hấp dẫn trên TopDev

Column Oriented Storage – The hidden thing 1

Column Oriented Storage

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Từ trước tới nay, làm với với Database là nhắc tới row (dòng), cũng có làm việc với column nhưng lưu trữ theo hướng column (Column Oriented Storage) thì chưa nghe bao giờ.

Đây, bắt đầu ngay xem tại sao ta lại cần biết về cái kiểu này.

  Khái niệm về OOD – Object oriented design
  Lập trình theo kiểu Aspect Oriented Programming (AOP) sử dụng Spring Framework

Một ngày đẹp trời, sếp đưa cho bạn một table với vài tỷ dòng dữ liệu. Nhắc lại là tỷ (trillion) nha. Sếp bảo lấy ra mấy dòng trong tháng 12 năm 2005. Lúc này, bất cứ thao tác nhỏ nào với DB cũng trở thành vấn đề lớn.

Column Oriented StorageKhông thiếu những câu hỏi thao tác, speeding up các table dữ liêu lớn

Rồi đây, cùng xem cái thằng quỷ Column Oriented Storage có gì khác?

1. Column Oriented Storage là gì?

Ý tưởng vô cùng đơn giản

The idea behind column oriented storage is simple: don’t store all the values from one row together, but store all the values from each column together instead

Ý tưởng phía sau column oriented storage vô cùng đơn giản: đừng lưu trữ tất cả dữ liệu trên một dòng, thay vào đó lưu trữ với nhau trên một cột

Nếu data trong mỗi column được lưu trữ trong một file?. Lúc này, khi cần truy xuất, chỉ cần đọc và parse nội dụng file sẽ có data. Tiết kiệm được rất nhiều thời gian và cải thiện rõ rệt về performance.

Column Oriented StorageNguồn ảnh / Source: Designing Data-Intensive Applications

Ở table phía trên, thay vì lưu trữ theo hướng row (hàng) ở phía trên, ta sử dụng column. Cột data_key, product_sk, tất cả chuyển qua lưu trữ theo dòng. Đó là bước đầu tiên trong Column Oriented Storage.

Cũng có thể nhớ dựa vào tên, Oriented: hướng về, thiên về. Nên Column Oriented Storage là lưu trữ theo hướng column (cột).

2. Nhanh hơn chỗ nào?

Column Oriented Storage
Column Oriented Storage
Column Oriented Storage

4. Tham khảo

Đã tìm hiểu về Column Oriented thì ngại ngùng gì mà không xúc luôn Database Clustering ha.

Thanks for read. Have a great day!. Happy coding!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

In ra màn hình số 1 – ngôn ngữ nào nhẹ nhất?

In ra màn hình số 1 - ngôn ngữ nào nhẹ nhất?

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

Nếu chỉ cần in ra mà hình số 1, ngôn ngữ lập trình nào sẽ chạy tốn ít RAM nhất?

Thí nghiệm sau sẽ cho ta thấy các chương trình cần bao nhiêu RAM để chạy và in ra số 1, kết thúc dòng bằng một dấu xuống dòng (newline \n).

Ta dùng chương trình /usr/bin/time để có cả thông số về RAM (RSS) thay vì chỉ gõ time – lệnh builtin của bash.

  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java
  4 ngôn ngữ phát triển game indie phổ biến

bash4.3

$ /usr/bin/time bash -c 'echo 1'

1

0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 3064maxresident)k

0inputs+0outputs (0major+136minor)pagefaults 0swaps

dash

$ /usr/bin/time /bin/dash -c 'echo 1'
1
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata 1492maxresident)k
0inputs+0outputs (0major+67minor)pagefaults 0swaps

mawk

$ /usr/bin/time mawk 'BEGIN {print 1}'

1

0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1932maxresident)k

0inputs+0outputs (0major+86minor)pagefaults 0swaps

gawk 4.1.3

$ /usr/bin/time gawk 'BEGIN {print 1}'

1

0.00user 0.00system 0:00.00elapsed 42%CPU (0avgtext+0avgdata 3632maxresident)k

552inputs+0outputs (2major+173minor)pagefaults 0swaps

Python3.5.2

$ /usr/bin/time python3 -c 'print(1)'

1

0.03user 0.01system 0:00.05elapsed 98%CPU (0avgtext+0avgdata 9292maxresident)k

0inputs+0outputs (0major+1100minor)pagefaults 0swaps

Python2.7.12

$ /usr/bin/time python2 -c 'print(1)'

1

0.01user 0.00system 0:00.01elapsed 94%CPU (0avgtext+0avgdata 6640maxresident)k

0inputs+0outputs (0major+819minor)pagefaults 0swaps

Ruby 2.3.1

$ /usr/bin/time ruby -e 'puts 1'
1
0.03user 0.01system 0:00.04elapsed 100%CPU (0avgtext+0avgdata 10336maxresident)k
0inputs+0outputs (0major+1595minor)pagefaults 0swaps

Perl v5.22.1

$ /usr/bin/time perl -e 'print "1\n"'

1

0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 4144maxresident)k

0inputs+0outputs (0major+176minor)pagefaults 0swaps

NodeJS 6.11.2

$ /usr/bin/time node -p '1'

1

0.09user 0.00system 0:00.10elapsed 100%CPU (0avgtext+0avgdata 24080maxresident)k

0inputs+0outputs (0major+2920minor)pagefaults 0swaps

Elixir 1.6.3

$ /usr/bin/time elixir -e 'IO.puts 1'

1

0.17user 0.04system 0:00.16elapsed 137%CPU (0avgtext+0avgdata 29268maxresident)k

16inputs+0outputs (1major+7837minor)pagefaults 0swaps

Guile 2.0.11

$ /usr/bin/time guile -c '(display 1) (newline)'

1

0.02user 0.00system 0:00.01elapsed 115%CPU (0avgtext+0avgdata 7720maxresident)k

0inputs+0outputs (0major+976minor)pagefaults 0swaps

printf 8.25 – chương trình viết bằng C

$ /usr/bin/time printf '1'

10.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1844maxresident)k

0inputs+0outputs (0major+72minor)pagefaults 0swaps

Làm lại toàn bộ bằng Python

Tạo một dictionary, chứa các tên ngôn ngữ – kèm với câu lệnh sẽ dùng để thử nghiệm

import shlex
import subprocess


programs = {
    'bash': 'bash -c "echo 1"',
    'dash': 'dash -c "echo 1"',
    'mawk': "mawk 'BEGIN {print 1}'",
    'gawk': "gawk 'BEGIN {print 1}'",
    'python2.7': 'python2 -c "print(1)"',
    'python3.5': 'python3 -c "print(1)"',
    'ruby2.3': 'ruby -e "puts 1"',
    'node6': 'node -p 1',
    'perl5': "perl -e \"print '1\n'\"",
    'elixir': 'elixir -e "IO.puts 1"',
    'guile': 'guile -c "(display 1) (newline)"',
    'printf': 'printf "1\n"'
}


import re

def get_rss_from_stderr(stderr):
    match = re.compile('(?P<rss>\d+)maxresident').search(err.decode('utf-8'))
    return int(match.group('rss'))


import pandas as pd

languages = []
rsses = []
for language, cmd in programs.items():
    cmd = ['/usr/bin/time'] + shlex.split(cmd)
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = process.communicate()
    assert out.decode('utf-8') == '1\n'
    rss = get_rss_from_stderr(err)
    print(language, rss)
    languages.append(language)
    rsses.append(rss)

df = pd.DataFrame(index=languages, data=rsses, columns=['RSS'])

df_sorted_rss = df.sort_values(by='RSS')

# run in Jupyter
from matplotlib import pyplot as plt
import matplotlib
matplotlib.style.use('fivethirtyeight')

%matplotlib inline
df_sorted_rss.plot.bar(title='RSS size in byte when print 1');

Dynamic typing languages

Kết luận

Khoan vội kết luận rằng cả thế giới nên chuyển hết về dùng dash cho đỡ tốn RAM hay xa lánh Elixir vì nó chạy tới 30 MB RAM để in số 1 ra màn hình.

Sử dụng đúng công cụ, cho đúng vấn đề thích hợp mới là điều quan trọng.

  • dash được viết ra để dùng làm shell (sh) cho Ubuntu, nó cần nhẹ, dù trả giá bằng việc không nhiều tính năng, và chỉ là một shell scripting language
  • bash là shell được dùng phổ biến nhất thế giới
  • awk là ngôn ngữ lập trình đã gắn liền với lịch sử của thế giới UNIX, rất tiện để tính toán dữ liệu cột / hàng. Với AWK cùng các CLI tool truyền thống, người ta có thể giải quyết bài toán “big data” nhanh gấp 200 lần dùng Hadoop (EMR)
  • mawk nhanh hơn gawk
  • perl5 luôn có chỗ đứng của nó, nó vẫn ở trên máy Ubuntu dù chưa bao giờ mình chủ ý cài
  • guile là extension language chính thức được lựa chọn bởi GNU, nó chính là ngôn ngữ scheme được mang vào ứng dụng thực tế
  • Python – ngôn ngữ dễ đọc, phổ biến nhất thế giới, đã đẩy ngành tính toán khoa học từ bộ môn trong phòng thí nghiệm trở thành ngành hot nhất trái đất. PS: Python khi bật lên đã dùng ~ 8MB RAM.
  • Ruby còn dùng nhiều RAM hơn nữa, dù về mặt tính năng thường được so ngang với Python, nhưng mặt ứng dụng vào khoa học thì là vực so với trời Python.
  • NodeJS là một JavaScript engine chuyển biến cả ngành web, cũng chưa rõ sao nó ngốn gần 25MB để bật lên, có khi đó vốn là bản chất của JavaScript.
  • Elixir không chỉ bật lên một interpreter như bash, mà đó là cả hệ thống phân tán – chạy máy ảo BEAM của Erlang, nên con số 30MB thậm chí còn là hơi … ít.

Bài này không xét các ngôn ngữ mà phải viết thành file, compile mới chạy, vì tác giả quá lười.

PS: học hết đống trên ở đây

Hết.

Bài viết gốc được đăng tải tại pp.pymi.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Hướng dẫn tạo certificate SSL trên ubuntu (file key, pem)

Hướng dẫn tạo certificate SSL trên ubuntu (file key, pem)

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Hướng dẫn tạo certificate SSL trên ubuntu (file key, pem)

(Xem thêm: Hướng dẫn tạo certificate SSL trên Windows (file key, pem))

Với server chạy bằng Java bạn cần chuyển file pem, private key sang p.12 (PKCS#12)

  System Design Cơ Bản: HTTPS, SSL, AND TLS
  Xử lý SSL Certificate trong Selenium WebDriver

Tạo file .key

openssl genrsa -out {ten_file}.key {do_dai_key}

Ví dụ:

openssl genrsa -out cert.key 2048

Hướng dẫn tạo certificate SSL trên ubuntu (file key, pem)

Tạo file .pem từ file .key

Cú pháp:

openssl req -x509 -new -nodes -key {ten_file.key} -sha256 -days 1825 -out {ten_file.pem}

Ví dụ:

openssl req -x509 -new -nodes -key cert.key -sha256 -days 1825 -out cert.pem

Sau đó nhập các thông tin của certificate như  email, name…

Bạn cũng có thể tạo file .crt, chỉ cần đổi đuôi .pem thành đuôi .crt là được

Demo:

Đây là thông tin SSL Certificate hiển thị trên trình duyệt khi mình dùng 2 file trên apply cho website của mình:

Hướng dẫn tạo certificate SSL trên ubuntu (file key, pem)

(Xem thêm: Cấu hình HTTPs cho Server NGINX)

Hướng dẫn tạo certificate SSL trên ubuntu (file key, pem)

Okay, Done!

References:

Bài viết gốc được đăng tải tại stackjava.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Prototype pattern – một trong những pattern phổ biến nhất

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Quay lại chuỗi bài viết về Design Pattern ở Kieblog, hôm nay vẫn tiếp tục là Creational Pattern (pattern khởi tạo), cụ thể là Prototype pattern.

Prototype pattern – một trong những pattern phổ biến nhất
Nguồn ảnh / Source: refactoring.guru

Trong cái pattern dễ nhất là Singleton Pattern, nắm vững. Sau đó quay qua tìm hiểu cái Prototype, pattern này cũng khá phổ biến, được sử dụng rất nhiều trong thực tế.

Bắt đầu vào tìm hiểu ngay thôi!.

  Design pattern là gì? Tại sao nên sử dụng Design pattern?
  Giải thích Flux Pattern theo phong cách John Wick

1. Prototype pattern là gì?

Bắt đầu với cái định nghĩa khá là lèo nhèo của Prototype pattern.

Prototype is a creational design pattern that lets you copy existing objects without making your code dependent on their classes.

Prototype là pattern khởi tạo cho phép copy một object sẵn có nhưng không làm đoạn code mới độc lập với class đã có

Vãi linh hồn cái định nghĩa. Loằng ngoằng, lèo ngèo khó hiểu. Thực ra thì diễn giải đơn giản chỉ như này.

Prototype pattern sẽ tạo ra một object mới bằng cách copy, tuy nhiên tương tự cách hiểu về kế thừa. Không cần phải copy ra đoạn source code mới, chỉ cần extends lại cái cũ là đã ok rồi

Prototype pattern – một trong những pattern phổ biến nhất
Thực tế lúc code không phải cái gì cũng nên copy ra. Không khéo thì từ “bay được” thành “đốt được”. Nguồn ảnh / Source: refactoring.guru

2. Giải pháp của prototype pattern

Về bản chất thì prototype sẽ định nghĩa ra các interface chung nhất (common interface) cho tất cả các object có hỗ trợ cloning. Những method này cho phép clone object. Mà thực hiện clone thì không cần copy source của object cũ.

Thông thường khi implement Prototype pattern, mỗi interface sẽ có duy nhất một phương thức clone.

Một object hỗ trợ cloning thì gọi là prototype. Prototype mang ý nghĩa cái chung nhất, cái common có thể cho những cái khác clone

Prototype pattern – một trong những pattern phổ biến nhất
Với prototype, có thể loại bỏ hoặc thay thế việc sử dụng quá nhiều subclassing. Nguồn ảnh / Source: refactoring.guru

3. Cấu trúc

Phần một (1) là phần khai báo iterface, method hỗ trợ cloning. Trong nhiều trường hợp, một interface chỉ có một method clone duy nhất.

Phần hai (2) là Concrete Prototype class, phần này sẽ implement cho method clone được khai báo ở interface. Cũng có thể handle một số case về các object không được clone.

Phần ba (3) là phần client có thể copy bất kì object nào thông qua phương thức clone

4. Hiện thực như nào?

Giả sử ta đang viết 3 class cho phần vẽ hình. Bao gồm hình tròn (Circle)

public class Circle extends Shape {
public int radius;

public Circle() {
}

public Circle(Circle target) {
super(target);
if (target != null) {
this.radius = target.radius;
}
}
// Method clone của Circle, trả về một object mới.
// Từ khóa this mang ý nghĩa state của tất cả các variable sẽ được giữ nguyên
@Override
public Shape clone() {
return new Circle(this);
}

@Override
public boolean equals(Object object2) {
if (!(object2 instanceof Circle) || !super.equals(object2)) return false;
Circle shape2 = (Circle) object2;
return shape2.radius == radius;
}
}

Và hình chữ nhật Rectangle

public class Rectangle extends Shape {
public int width;
public int height;

public Rectangle() {
}

public Rectangle(Rectangle target) {
super(target);
if (target != null) {
this.width = target.width;
this.height = target.height;
}
}

@Override
public Shape clone() {
return new Rectangle(this);
}

@Override
public boolean equals(Object object2) {
if (!(object2 instanceof Rectangle) || !super.equals(object2)) return false;
Rectangle shape2 = (Rectangle) object2;
return shape2.width == width && shape2.height == height;
}
}

Abstract class của 2 thằng này là Shape. Tất nhiên, tròn hay vuông thì đều là một cái hình mà thôi

public abstract class Shape {
public int x;
public int y;
public String color;

public Shape() {
}

public Shape(Shape target) {
if (target != null) {
this.x = target.x;
this.y = target.y;
this.color = target.color;
}
}
// Shape cũng có method abstract riêng của nó
public abstract Shape clone();

@Override
public boolean equals(Object object2) {
if (!(object2 instanceof Shape)) return false;
Shape shape2 = (Shape) object2;
return shape2.x == x && shape2.y == y && Objects.equals(shape2.color, color);
}
}

Khi sử dụng, phương thức clone sẽ sử dụng như sau

public static void main(String[] args) {
List<Shape> shapes = new ArrayList<>();
List<Shape> shapesCopy = new ArrayList<>();

Circle circle = new Circle();
circle.x = 10;
circle.y = 20;
circle.radius = 15;
circle.color = "red";
shapes.add(circle);

// Dễ dàng có thể tạo ra một object clone mới, không duplicate source, source đẹp rõ ràng
Circle anotherCircle = (Circle) circle.clone();
shapes.add(anotherCircle);

Rectangle rectangle = new Rectangle();
rectangle.width = 10;
rectangle.height = 20;
rectangle.color = "blue";
shapes.add(rectangle);

cloneAndCompare(shapes, shapesCopy);
}

5. Ưu nhược điểm

Đầu tiên, rõ ràng là sử dụng Prototype pattern không làm cho code độc lập với cái class mà nó clone. Chắc chắn.

Thứ hai, dùng prototype pattern giúp clone object một cách nhanh chóng, không bị duplicate code. Trường hợp object phức tạp, chứa rối rắm nhiều thứ, Prototype là lựa chọn tuyệt vời.

Tuy nhiên, nếu object có tham chiếu hoặc kế thừa từ các object khác. Clone thì dễ, nhưng không biết mức độ ảnh hưởng tới đâu. Nếu object clone có dây mơ rễ má nhiều chỗ -> rất dễ trở thành một đám tơ vò.

6. Tham khảo

Ở phía bên Javascript có thể tham khảo bài viết về prototype cũng khá hay.

Thanks for read – Have a great day – Happy coding!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Todo List: Hiển thị thông báo trong ứng dụng Laravel

Todo List: Hiển thị thông báo trong ứng dụng Laravel

Bài viết được sự cho phép của tác giả Kien Dang Chung

Video trong bài viết

Trong bài Kiểm tra dữ liệu, chúng ta đã hiển thị các thông báo về lỗi nhập liệu đến người dùng, các thông báo này rất cần thiết để người dùng biết được trạng thái nhập liệu. Ngoài những thông báo lỗi, chúng ta còn những thông báo cần thiết khác, ví dụ như khi đã thực hiện xong một công việc nào đó.

  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth
  Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream

Laravel Session lưu dữ liệu dùng chung trong phiên

Như các bạn đã biết, HTTP là giao thức stateless tức là giao thức không trạng thái, các lần truy cập khác nhau sẽ không liên quan và lưu trữ trạng thái của nhau. Chính vì vậy, để lưu trữ thông tin qua các lần truy cập khác nhau, chúng ta có Laravel Session.

Session trong Laravel có thể lưu trữ ở các dạng như file, database, cookie và cả memcache… Để lưu trữ thông tin giữa các lần truy cập rất đơn giản sử dụng cú pháp như sau:

$request->session()->put('key', 'value');

Thông tin lưu trữ ở dạng cặp (key, value), muốn lấy thông tin này thì sử dụng:

$request->session()->get('key');

Lưu trữ dữ liệu nhanh

Đôi khi chúng ta chỉ muốn lưu trữ các thông tin cho đến request tiếp theo, ví dụ khi thao tác dữ liệu ở request hiện tại, trong request tiếp theo chúng ta muốn hiển thị trạng thái là đã thao tác thành công. Các dữ liệu này ở những request kế tiếp đó sẽ bị xóa đi. Để lưu trữ các dữ liệu nhanh này chúng ta sử dụng cú pháp:

$request->session()->flash('success', 'Create todo successful!');

Hiển thị thông báo

Trong các bài học trước, chúng ta mới chỉ hiển thị lỗi khi kiểm tra dữ liệu, trong bài này chúng ta sẽ sử dụng Laravel Session để lưu trữ thông tin giữa các request và hiển thị thông báo khi các thao tác với bản ghi Todo hoàn thành.

Đầu tiên, chúng ta sẽ thực hiện hiển thị thông báo khi lưu trữ Todo thành công, việc lưu trữ này do phương thức store() trong TodosController đảm nhận, sau khi thực hiện save dữ liệu chúng ta sẽ lưu thông tin trạng thái vào Session và trong request tiếp theo sẽ hiển thị nó lên:

public function store()
{
    $this->validate(request(), [
        'name' => 'required|min:6|max:12',
        'description' => 'required'
    ]);

    $data = request()->all();

    $todo = new Todo();
    $todo->name = $data['name'];
    $todo->description = $data['description'];
    $todo->completed = false;
    $todo->save();

    session()->flash('success', 'Todo created successfully.');

    return redirect('/todos');
}

Ở đây sau khi lưu dữ liệu xuống database, chúng ta lưu thông tin (‘success’, ‘Todo created successfully.’) vào Session. Trong request tiếp theo chính là redirect(‘/todos’) là trang danh sách todos, chúng ta hiển thị thông báo này. Chú ý là thông báo này sẽ hiển thị ở các trang khác nhau, do đó sẽ đưa phần hiển thị vào file bố cục resources/views/layouts/app.blade.php:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
  <title>
    @yield('title')
  </title>
</head>
  <body>
      <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="/">Todos App</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
              <a class="nav-link" href="/todos">todos <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item active">
              <a class="nav-link" href="/new-todos">Create todos <span class="sr-only">(current)</span></a>
            </li>
          </ul>
        </div>
      </nav>
    <div class="container">
      @if(session()->has('success'))
        <div class="alert alert-success">
          {{ session()->get('success') }}
        </div>
      @endif
      @yield('content')
    </div>
  </body>
</html>

Thử tạo mới một Todo chúng ta sẽ có thông báo “Todo created successfully!” khi hoàn thành.

Hiển thị thông báo khi tạo Todo

Tương tự với trường hợp cập nhật và xóa dữ liệu chúng ta cập nhật các phương thức update() và destroy() trong TodosController như sau:

public function update(Todo $todo)
{
    $this->validate(request(), [
        'name' => 'required|min:6|max:12',
        'description' => 'required'
    ]);

    $data = request()->all();

    $todo->name = $data['name'];
    $todo->description = $data['description'];
    $todo->save();

    session()->flash('success', 'Todo updated successfully.');

    return redirect('/todos');
}

public function destroy(Todo $todo)
{
    $todo->delete();

    session()->flash('success', 'Todo deleted successfully.');

    return redirect('/todos');
}

Source code: Bài 16 – Hiển thị thông báo thông qua Laravel Session

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm tuyển lập trình Laravel hấp dẫn trên TopDev

Awk siêu tốc

Awk siêu tốc

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

Nếu bạn đã biết 1 scripting language như Python hay Perl việc học AWK sẽ có vẻ hơi thừa/ hơi ngần ngại. Nhưng AWK – ngôn ngữ lập trình sinh ra từ những năm 1970 luôn có chỗ dùng, và sức mạnh đáng gờm.

  10 hiểu lầm tai hại về lập trình
  10 nguyên tắc lập trình nền tảng mà lập trình viên nào cũng cần biết

Bài này giới thiệu các khái niệm cơ bản của ngôn ngữ lập trình AWK, một số cách dùng thông dụng, học xong có thể dùng ngay và vô cùng hữu ích với những người xử lý dữ liệu dạng cột/ bảng mà không biết Python.

Các lệnh trong bài này dùng mawk vì nó được biết là nhanh hơn các bản awk khác, nhưng về tính năng cơ bản là giống nhau, người đọc dùng bản nào cũng được, VD gawk

$ whatis awk
awk (1)              - pattern scanning and processing language

Dùng trong các câu lệnh hàng ngày

AWK rất thích hợp để nhét vào 1 pipe các câu lệnh UNIX, việc mà Python vốn không sinh ra để làm

Ví dụ: đếm số dòng trong file /etc/passwd

$ wc /etc/passwd
  57   95 3193 /etc/passwd

Lệnh wc vốn sinh ra để đếm: dòng, số từ, số ký tự. Bạn có thể viết 1 script Python 5-7 dòng làm chuyện này, nhưng 1 dòng? Hãy thử và nếu thành công, hãy comment!

Với AWK, làm việc này không khó khăn gì. Hãy bỏ qua nếu không hiểu gì, phần giải thích sẽ theo sau

$ cat /etc/passwd | mawk '{ words += NF; chars += length($0) + 1;} END { print NR, words, chars}'
57 95 3193

Một pipe (cmd1 | cmd2 | cmd3) thường bắt đầu bằng cat file, mặc dù nó không phải cách làm tốt (tốn thêm 1 câu lệnh cat – khi mà hầu hết các câu lệnh đều hỗ trợ đầu vào là 1 file), nhưng tiện, nên ta cứ bắt đầu với cat, khi nào cần tối ưu ta sẽ bỏ nó đi. Ở đây, mawk có thể nhận file để xử lý, ta viết lại:

$ mawk '{ words += NF; chars += length($0) + 1;} END { print NR, words, chars}' /etc/passwd
57 95 3193

Một ví dụ khác

$ head /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

Một yêu cầu quái dị có thể xuất hiện như: hãy tính tổng các số ở cột số 3, với các câu lệnh CLI truyền thống, ta làm như sau

$ echo $(cat /etc/passwd | cut -d: -f3 | xargs printf '%s +') 0 | bc
75624

cut giúp lấy cột thứ 3, phân cách bằng dấu :, dùng printf để nối các số lại bằng dấu +, vì thừa 1 dấu + ở đuôi nên ta echo thêm số 0 để cho hợp lệ rồi đưa vào lệnh bc để tính.

$ mawk -F: '{sum += $3} END { print sum }' /etc/passwd
75624

Tương tự cut, ta dùng -F: để chỉ ra sẽ dùng : để phân cách cột, lấy cột số 3 $3, cộng lần lượt các giá trị vào biến sum – khi ta không khai báo, AWK mặc định đó là số 0 nếu thực hiện phép toán với số. Làm như vậy với mỗi dòng (gọi là record trong AWK):

{ sum += $3 }

Và khi hết các dòng (đánh dấu bằng END), ta print ra kết quả

END { print sum }

Khó có thể đánh bại sự ngắn gọn, sạch sẽ này.

Record và field

AWK đọc text vào, mặc định sẽ cắt tại các dấu xuống dòng, tạo thành các record, sau đó mặc định cắt tại dấu space (khoảng trắng), tạo thành các field. Ta hoàn toàn có thể chỉ định AWK cắt ở ký tự khác.

Cấu tạo một chương trình AWK

Một chương trình AWK cấu tạo bởi các câu lệnh (statements) với cú pháp:

              pattern   { action statements }

Chỉ có vậy. Khi viết vào file thì viết mỗi câu lệnh 1 dòng, nhưng hoàn toàn có thể viết trên 1 dòng.

partern

Có nhiều partern, nhưng 3 partern phổ biến và hữu ích nhất là:

  • BEGIN: theo sau là hành động / câu lệnh khi chương trình bắt đầu
  • END: theo sau là câu lệnh được chạy khi chương trình kết thúc
  • KHÔNG GHI PATTERN: thực hiện câu lệnh này cho mỗi record

Ví dụ

'{sum += $3} END { print sum }'

Ví dụ sau không có BEGIN, với mỗi record ta sẽ cộng dồn, và khi đọc hết các record, ta print ra tổng. Chú ý: dấu \ ở cuối dòng là cú pháp trong shell cho phép viết 1 dòng thành nhiều dòng, khi chạy AWK chỉ xem toàn bộ chương trình là 1 dòng.

$ echo 'pymi\npython\nfamilug' | mawk '\
 BEGIN { print "the begin" } \
 { printf "got line: %s has length %d\n", $0, length($0) }\
 { print "done process line ", NR }\
 END {print "DONE"}'

the begin
got line: pymi has length 4
done process line  1
got line: python has length 6
done process line  2
got line: familug has length 7
done process line  3
DONE

parttern tìm kiếm

parttern này giúp tìm kiếm các record có chứa một regular expression (hoặc string cố định) và xử lý record đó.

Đếm số dòng chứa từ print:

$ echo -e "printf print \nprintf"
printf print
printf
$ echo -e "printf print \nprintf" | grep -c print
2
$ echo -e "printf print \nprintf" | mawk '/print/ { count += 1 } END { print count }'
2

print

print và printf là 2 output statements (câu lệnh xử lý đầu ra), không phải function nên không sử dụng cú pháp gọi function print(thing)

$ mawk 'BEGIN { print "hello" }'
hello

variable và field variable

Mỗi record chứa nhiều field, hãy tưởng tượng như 1 dòng spreadsheet/excel có nhiều ô ứng với các cột. Các variable có sẵn:

  • $0 – toàn bộ 1 record (dòng) – chú ý dấu $ dùng để truy cập giá trị của field
  • $1 – field 1 (hay có thể nghĩ là cột số 1)
  • $2 – field 2
  • $(NF - 1) – field trước cuối cùng
  • $NF – field cuối cùng
  • NF – số field
  • NR – thứ tự của record, tăng dần sau khi xử lý xong mỗi record (số dòng hiện tại)

Khi truy cập biến, không sử dụng thêm bất cứ ký tự nào (khác với bash, bash phải thêm $varname).

$ echo '1, Le Van Xe, 27, Ha Noi, 0990090090' | mawk -F, '{ print $NF}'
 0990090090
$ echo '1, Le Van Xe, 27, Ha Noi, 0990090090' | mawk -F, '{ print $0}'
1, Le Van Xe, 27, Ha Noi, 0990090090
$ echo '1, Le Van Xe, 27, Ha Noi, 0990090090' | mawk -F, '{ print NF }'
5

Chỉ cần nắm rõ tên các variable có sẵn này, ta đã có một tool cực mạnh để xử lý dữ liệu dạng bảng như Excel/CSV/SQL.

Các kiểu dữ liệu

AWK có string, số (chia làm float và integer), và array. Ta không bàn tới array ở đây, vì nếu cần lập trình gì phức tạp hơn một câu lệnh AWK đơn giản, ta có thể sử dụng Python cho sạch sẽ, gọn gàng, tiện lợi.

Control flow

Là ngôn ngữ lập trình đầy đủ, AWK có if/else/for/while như các ngôn ngữ lập trình “giống C” khác. Ví dụ đếm số chẵn và số lẻ

$ echo -e '1\n2\n3\n4\n20\n30' | mawk '\
{ if ($1 % 2 == 0) \
     { chan += 1 } \
  else { le += 1 } \
} \
END { print chan, le }'

5 1

Function

AWK có sẵn các funtion xử lý string, số thì đủ các phép toán, các function sin cos …, người dùng cũng có thể định nghĩa function của họ. Xem thêm ở đây.

Bonus – giải bài projecteuler 1

Tính tổng các số nhỏ hơn 1000 chia hết cho 3 hoặc 5

$ seq 1 999 | mawk '{ if ($1 % 3 == 0 || $i % 5 == 0) sum += $1 } END { print sum }'
233168

Tham khảo

Hết

Bài viết gốc được đăng tải tại pp.pymi.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Hướng dẫn sử dụng Xcode và Tạo project Xcode

Hướng dẫn sử dụng Xcode và Tạo project Xcode

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Hướng dẫn sử dụng Xcode và Tạo project Xcode

1.Cài đặt môi trường và các công cụ cần thiết

1.1.Tạo tài khoản apple develop

1.2.Tải Xcode

Các bạn tải tại đây https://developer.apple.com/xcode/

Xcode là 1 IDE do apple phát triển ,giúp lập trình viên có thể thiết kế các giao diện và viết các câu lệnh code điều khiển, biên dịch và chạy trên Simulator hoặc trên các máy thật iphone.

Hiện nay, hệ điều hành Mac OS X Yosemite được cung cấp miễn phí, mình khuyên các bạn nên tải về và sử dụng, việc này hỗ trợ tốt hơn cho bạn tong quá trình lập trình.

  "Code dễ đọc" là như thế nào?
  "Mẹo bỏ túi" cho dân coder mới vào nghề

2.Tạo project

Khi bạn mở Xcode lên sẽ hiện lên 1 cửa sổ giao diện như sau

Hướng dẫn sử dụng Xcode và Tạo project Xcode

Bên phải là các project chúng ta đã tạo và là trước đó.

Đầu tiên bạn mở Xcode lên và chọn “Create a new Xcode project“, sau đó lại có 1 cửa sổ hiện lên bạn chọn “Single View Application”  để Xcode tạo cho bạn 1 dự án và màn hình đơn.  “Single View Application” là dạng project trắng và chỉ có 01 “màn hình” duy nhất.

Hướng dẫn sử dụng Xcode và Tạo project Xcode

Và khi bạn click Next thì  sẽ hiển thị 1 cửa sổ tiếp theo :

tạo project xcode

  • Product Name: Tên ứng dụng.
  • Organization Name: tên cơ quan, tổ chức hoặc tên lập trình viên.
  • Organization Identifier: tên định danh của cơ quan, tổ chức hoặc của lập trình
    viên.
  • Language: ngôn ngữ lập trình mà bạn sẽ sử dụng trong quá trình lập trình

Khi chúng ta tạo xong thì giao diện Xcode sẽ như đầy đủ như thế này

tạo project xcode

Hướng dẫn sử dụng Xcode và Tạo project Xcode

Xcode sẽ hiển thị thông tin dự án này trog khung Editor

Trong workspace, có thể bạn sẽ nhìn thấy biểu tượng lỗi với thông điệp là “Signing for FoodTracker requires a development team“. Đừng lo lắng nhé, bạn hãy cứ bỏ qua nó mà vẫn có thể lập trình một các bình thường. Cảnh báo này có nghĩa là bạn cần có một nhóm để phát triển ứng dụng.

  • ToolBar: Đây là thanh công cụ của XCode. Tại đây bạn có thể theo dõi trạng thái ứng dụng, chạy thử, bật tắt một vài thành phần giao diện khác.
  • Navigator area: Đây là nơi bạn có thể xem cấu trúc project, trạng thái lỗi, …

File  .swift là các tập tin dùng để viết mã điều khiển đối tượng, triển khai thuậ toán. Phần mở rộng là .storyboard thiết kế giao diện người dùng. Ngoài ra còn có các tập tin .framework là các thư viện được sử dụng trong ứng dụng và các tập tin .plist chứa các thông tin cơ bản và thông tin mở rộng của ứng dụng.

  • Editor area: tại đây bạn có thể viết code hoặc thiết kế giao diện.
  • Utility area: nơi cấu hình giá trị cho các thuộc tính của thành phần giao diện.

Và đây là thành quả sau khi bạn tạo project và run trên máy ảo:

điện thoại trắng

Một số phím tắt cơ bản

Command + mũi tên trái: Xoay bên trái của thiết bị

Command + mũi tên phải: Xoay điện thoại

Ctrl + Command + Z: Giả lập cử chỉ lắc

Hy vọng bài hôm nay sẽ giúp các bạn hiểu chi tiết về các thành phần cơ bản trong Xcode.

Bài viết gốc được đăng tải tại codecute.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Load Balancers II – Determine which servers processes a request

Load Balancers II – Determine which servers processes a request

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Trở lại chuỗi bài viết chuyên sâu về Load Balacers và Web Server. Biết về khái niệm và cách mà Load Balancers cân bằng lượng request đến đã là tốt.

Tuy nhiên, request ở máy A sẽ đi tới servers nào khi ta có tới cả 100 servers service nhỏ?.

  Angular - Tự xây dựng module "lazy load images"
  Cân bằng tải (Load Balancing)

Để trả lời cho câu hỏi này, hãy cùng nhìn lại chút xíu về Load Balancers Architecture.

Load BalancersThông qua sự “điều tiết” của Web Balancers, nhiều Application Servers nhỏ có thể handle một lượng request lớn.

1. Phán định servers

Vấn đề là Application nào sẽ handle request nào?. Ví dụ: client A ở lần request đầu tiên sẽ gửi tới Application Servers A do Load Balancers điều phối.

Gọi là phán định servers vì không thể ở request thứ nhất, Application Servers A xử l. Request thứ hai lại do Application Servers B xử.

Để có phá định chuẩn rằng Servers nào nên xử lý request nào thì ta cần hiểu rõ về Application Servers trước. Đặc điểm chính là Stateless. Vậy Stateless là gì?.

2. Stateless trong Load Balancers

Stateless có thể được hiểu như là không state. Tại sao nói không State?.

State là trạng thái, mỗi request gửi lên Servers đều mang một trạng thái của riêng nó. Tạo mới, cập nhât, xóa bỏ, … Chữ less ở đây mang ý nghĩa Application Servers sẽ không chịu trách nhiệm lưu trữ State của request.

Load Balancers

Đọc tới đây có bạn sẽ hỏi nếu App Servers lưu trữ State thì sao?. Lấy ví dụ luôn.

Giả sử khách hàng A đang có 2 sản phẩm trong giỏ (2 products). Load Balancers ban đầu phán định App Servers 5 sẽ xử lý request này. Do 4 cái còn lại đang busy.

Vậy nếu khách hàng cập nhật giỏ hàng, thêm xóa bỏ, mua mới?. Mọi request liên quan tới giỏ hàng này đều phải thông qua App Servers 5?

Giữ App Servers 5 cho một giỏ hàng thì quá lã lãng phí. Cũng không đảm bảo sự hoạt động trơn tru của Load Balancers. Chính vì vậy, App Servers giữ trong mình nó chữ Stateless.

Không quan tâm tới state đảm bảo cho mọi server có trách nhiệm và chức năng như nhau. Ai rảnh thì vào xử lý request ngay, không cần quan tâm tới state của request được gửi là như thế nào.

3. Scaling

Giữ cho các App Servers tách biệt với state cũng đảm bảo về khả năng Sclaing khi application mở rộng. Các App Servers có thể độc lập hoạt động mà không cần quan tâm tới state được gửi lên từ request như thế nào.

Load Balancers

Về scalable trong web application thì có thể đọc qua bài viết này. Tìm hiểu thêm về Horizontal và Vertical Scaling.

4. Tổng kết

Quay lại câu hỏi ngay từ ban đầu. Với kiến trúc Distributed Server và Distributed Database. Phán định server nào xử lý request như thế nào?

Câu trả lời là phán định do Load Balancers chỉ định tùy thuộc tình trạng busy hiện tại của các Server khác. Về bản chất thì các App Servers có chức năng tương tự nhau, có thể hoạt động độc lập với nhau.

5. Tham khảo

Thank for reading – Have a nice yearend – Happy coding!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Transaction Processing – Everything must know

Transaction Processing

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Gì chứ nhắc tới Transaction Processing thì không một Software Engineer nào là không hiểu tường, hiểu tận. Biết có thể chỉ là một phần kiến thức nhỏ, nhưng những khái niệm đặc biệt như transaction cần phải nắm thật vững.

Bài viết này cung cấp một cái nhìn toàn diện, từ cơ bản cho tới nâng cao về Transaction Processing. Thứ được biết đến như là khái niệm cốt lỗi của Database actions, Payment Steps,…

Bắt đầu ngay thôi!

  10 tuyệt kĩ từ trang web nhanh nhất thế giới (phần 1)
  Khái niệm transaction trong database

1. Transaction là gì?

Rõ luôn là phải hiểu transaction là gì trước khi bắt tay vào tìm hiểu Transaction Processing. Ok, khái niệm. Có 3 thứ cần nhớ.

A unit of information processing that is indivisible.

Transaction là một đơn vị của “tiến trình xử lý thông tin” không thể phân chia

Đọc rõ khó hiểu, nhưng túm cái váy lại: transaction là một đơn vị, nó độc lập và không thể chia nhỏ hơn được.

It must either success or fail as a complete unit.

Nó phải thành công hoặc thất bại như là một đơn vị hoàn chỉnh

Đã nhắc tới transaction processing thì lúc kết thúc process, transaction nhất định phải có kết quả là thành công (sucess) hoặc thất bại (fail). Các transaction pending ta thường thấy cũng là đang quá trình chờ đợi. Nói về status khi kết thúc transaction, luôn nhớ rằng một là thành công hai là thất bại. Không có chuyện giữa giữa.

It can never only partically complete.

Transaction không bao giờ hoàn thành một phần

Ví dụ như giao dịch ở ngân hàng. Nếu success -> tiền chuyển đi, nếu fail -> thực hiện transaction mới. Giao dịch kiểu transaction không bao giờ có chuyện thành công một nửa, hoặc chỉ thất bại ở một step nào đó.

Đã fail dù chỉ một tiến trình nhỏ trong transaction cũng khiến cả transaction bị fail.

2. Ví dụ về Transaction Processing

Lý thuyết rõ dài, thôi thì cho xin cái ví dụ để dễ hiểu hơn.

Đây là ví dụ đơn giản nhất về mua vé máy bay. Hiện tại đang còn 5 vé có giá tốt. Mà các ông thì đã mua vé rồi, giờ làm sao để mua được vé giá tốt?.

transaction processing là gì?

Có 3 bước phải tiến hành như sau:

  • 1. Trả lại vé cũ đã mua với giá hơi chát.
  • 2. Cập nhật số lượng chuyến bay còn giảm giá khi đã mua.
  • 3. Thanh toán vé đã mua với số tiền “thơm”.

Hoàn thành cả 3 bước được gọi là một transaction. Trường hợp này, trong một unit, ta phải thực hiện thành công cả 3 actions. Chỉ một trong đó fail cũng khiến transaction thất bại -> vé không mua được.

Ví dụ thì dễ hiểu rồi, giờ tới vấn đề của chữ Processing.

3. Transaction process được hiện thực như thế nào?

Nhắc tới transaction mà focus vào process thì luôn phải nhớ “Two Phase Commit”. Từ khóa này đặc biệt quan trọng, cũng là thứ để biết Sofware Engineer đã hiểu rõ về Transaction Processing hay chưa.

Phase ở đây mang nghĩa là “giai đoạn”, một transaction sẽ trải qua hai giai đoạn để hoàn thành.

3.1 Commit request

Giả sử ta có 3 database A,B và C. Thiết kế cho Scalable Web Application chẳng hạn. Bước đầu tiên của Two Phase Commit là “Commit Request”.

Ở bước này, services hay workers sẽ gửi request tới từng database A,B,C. Request này gần giống như request thật về nội dung. Nói vậy nghĩa là sao.

Khi nhận được request từ phase 1 -> tất cả đều thực hiện thử cập nhật. Trả kết quả về cho services.

hiểu về transaction processSau khi tiến hành cập nhật thử ở DB, kết quả lần lượt được trả về (Yes – có khả năng cập nhật, No – không thể cập nhật).

3.2 Commit

Sau khi kết thúc Commit Request và nhận về được tất cả kết quả từ A,B,C (Return Result). Process Commit sẽ đưa ra phán định cho biết commit của Transaction Processing có thành công hay không?.

Nếu cả 3 đều PASS -> Rõ ràng là transaction thành công. Trường hợp một trong 3 fail -> transaction sẽ phán định fail và thực hiện xử lý tiếp theo.

Transaction processing là gì?Bước thứ 2 của Transaction Process sẽ là phán định kết quả (return result) từ step thứ nhất.

Xử lý tiếp theo ở đây là rollback. Từ rollback thì quen quá rồi.

Trường hợp thất bại, tất nhiên ta không muốn bất cứ dòng dữ liệu nào xuất hiện ở A và B, mặc dù Commit Request báo PASS. Lúc này phase số 3 (có phase 3 tuy nhiên vẫn gọi Two-phase vì nó là chính).

Việc thực hiện Commit Request để lấy result tất nhiên không thực hiện luôn ở Global Database. Sau khi có kết quả Success -> Global sẽ trả lại data như ban đầu trước khi gửi request success.

  1. After receiving notice from the global coordinator that all nodes have committed, the commit point site erases status information about this transaction. – Sau khi nhận được thông báo từ Global rằng tất cả được commit, thông báo cuối cùng về trạng thái commit được trả về.
  2. The commit point site informs the global coordinator that it has erased the status information. – Global lúc này sẽ xóa đi thông tin commit
  3. The global coordinator erases its own information about the transaction. – Sau đó cũng xóa luôn đi thông tin của cả transaction.

4. Tham khảo

Thank you for your attention – Have a good day. Happy Coding!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

IronPython

IronPython

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

IronPython là gì?

Theo giới thiệu ở trang chủ IronPython:

IronPython is an open-source implementation of the Python programming language which is tightly integrated with the .NET Framework. IronPython can use the .NET Framework and Python libraries, and other .NET languages can use Python code just as easily.

Ironpython là 1 “implementation” mã nguồn mở của ngôn ngữ lập trình Python, tích hợp chặt chẽ với .NET Framework. IronPython có thể sử dụng .NET Framework và các thư viện Python, các ngôn ngữ .NET khác cũng có thể đọc và chạy code Python dễ dàng.

  File I/O trong Python

Cài đặt IronPython

Vào trang chủ download bộ cài đặt về (link download ở trang chủ là link github). Thời điểm viết bài, IronPython đang ở phiên bản 2.7.8. IronPython 3 đang trong quá trình phát triển, chưa có bản chính thức.

Sử dụng

  • Bật IronPython interpreter bằng cách chạy (bấm đúp – double click) vào file ở đường dẫn: C:\Program Files (x86)\IronPython 2.7\ipy.exe hoặc C:\Program Files (x86)\IronPython 2.7\ipy64.exe. Hoặc bấm nút Start -> gõ cmd -> Enter, sau khi cửa sổ Command Prompt hiện lên thì gõ đường dẫn file: C:\Program Files (x86)\IronPython 2.7\ipy.exe hoặc C:\Program Files (x86)\IronPython 2.7\ipy64.exe:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\HTL>"c:\Program Files (x86)\IronPython 2.7\ipy.exe"
IronPython 2.7.3 (2.7.0.40) on .NET 4.0.30319.42000 (32-bit)
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello from IronPython")
Hello from IronPython
  • Chạy 1 python script đã viết sẵn bằng cách gõ vào Command Prompt: C:\Program Files (x86)\IronPython 2.7\ipy.exe đường_dẫn\đến\script.py. Ví dụ nội dung file D:\HTL\Desktop\script.py:
print("Hello from inside a Python script")
C:\Users\HTL>"c:\Program Files (x86)\IronPython 2.7\ipy.exe" D:\HTL\Desktop\script.py
Hello from inside a Python script
  Thư viện Python: Cái nào tốt nhất cho vai trò gì?

Sử dụng .NET Framework và Python libraries

IronPython có sẵn thư viện clr hỗ trợ load các .NET Assemblies (VD như các file .dll) và sử dụng các công cụ trong đó. IronPython cũng có các libraries kèm theo tương tự như CPython:

C:\Users\HTL>"c:\Program Files (x86)\IronPython 2.7\ipy.exe"
IronPython 2.7.3 (2.7.0.40) on .NET 4.0.30319.42000 (32-bit)
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr
>>> clr.AddReference('System')
>>> from System import Environment
>>> print(Environment.SystemDirectory)
C:\Windows\system32
>>> import math
>>> print(math.pi)
3.14159265359

Tài liệu IronPython

Tương tự câu hỏi khi học Python thì dùng tài liệu nào, đối với IronPython thì cũng lấy tài liệu ở trang chủ. IronPython Documentation có 2 phần: phần 1 chính là Python 2.7 documentation, phần 2 là hướng dẫn tích hợp .NET với IronPython.

Kết luận

  • Học ngôn ngữ Python là có thể sử dụng trên nhiều môi trường, với nhiều implementation khác nhau (CPython, IronPython, Jython…).
  • IronPython là sự lựa chọn hợp lý khi làm việc với môi trường Windows và các phần mềm chạy trên Windows.
  • Alternative: Trả lời cho câu hỏi “Mình vẫn muốn dùng CPython và vẫn muốn sử dụng .NET Framework thì làm như thế nào?” -> Tìm hiểu pythonnet nhé. Tuy nhiên mình khuyến khích dùng IronPython để làm việc trên Windows và các phần mềm chạy trên Windows.

Bài viết gốc được đăng tải tại pp.pymi.vn

Có thể bạn quan tâm:

Xem thêm tuyển python lương cao hấp dẫn trên TopDev

Biến số và kiểu dữ liệu số trong Python

Biến số và kiểu dữ liệu số trong Python

Bài viết được sự cho phép của tác giả Kien Dang Chung

Trong lập trình biến và kiểu dữ liệu là những khái niệm cơ bản nhất, từ những khái niệm cơ bản này chúng ta mới tiếp tục những phần nâng cao hơn như tương tác với người dùng, các cú pháp điều khiển luồng ứng dụng, thuật toán… Khóa học này nhắm đến cả những bạn mới bắt đầu làm quen với lập trình do đó nội dung đi khá chi tiết, bạn nào đã có kiến thức sẵn có thể xem các bài tiếp theo.

1. Biến số

1.1 Biến số trong ngôn ngữ lập trình là gì?

Biến số (variable) là một khái niệm cơ bản trong lập trình, biến dùng để lưu trữ thông tin, các tham chiếu và sử dụng để thao tác dữ liệu. Các biến bản chất là một cách để đánh nhãn cho dữ liệu với một tên gợi nhớ, các chương trình có thể hiểu được cần lấy dữ liệu từ đâu với biến đó. Đặt tên biến gợi nhớ cũng giúp cho các lập trình viên khác có thể hiểu được đoạn code bạn chia sẻ. Một hình tượng khác có thể dễ hiểu hơn là các biến giống như những chiếc công tơ nơ chứa bên trong các nội dung là đồ vật, hàng hóa… được đánh số (đặt tên) ví dụ công tơ nơ thực phẩm, công tơ nơ đồ điện giúp cho muốn tìm đến một loại hàng hóa nào đó dễ dàng.

Trong Python, các biến được khai báo với cú pháp như sau:

ten_bien = gia_tri

Trong đó:

  • ten_bien: là một tên gợi nhớ cho dữ liệu cần xử lý, ví dụ tuoi_nguoi_dung, tong_so_tien… Chú ý nên đặt tên gợi nhớ giúp cho người khác hoặc chính bản thân bạn có thể đọc lại code một cách dễ dàng, tránh các tên biến theo kiểu abc, xyz, heeeeee, hiiiii…
  • gia_tri: là giá trị khởi tạo cho biến, giá trị này sẽ được lưu vào bộ nhớ máy tính và khi chương trình cần dùng đến dữ liệu này sẽ gọi đến tên biến. Giá trị có thể là số, chuỗi ký tự hoặc thậm chí là một hàm tính toán khác.

Quay lại ví dụ Hello world trong bài trước, chúng ta in ra màn hình một lời chào bằng câu lệnh print(). Tiếp theo, chúng ta sẽ sử dụng một biến lưu trữ câu chào và thực hiện in ra màn hình câu chào thông qua biến này.

loi_chao = "Hello, world!"
print(loi_chao)

Kết quả là giống nhau, vậy tại sao cần sử dụng biến trong Python? Mình sẽ ví dụ cho các bạn thấy tại sao cần biến số, ví dụ người dùng nhập vào tên và chúng ta in ra lời chào. Như vậy tên người dùng nhập vào cần được lưu trữ trong một biến ten_nguoi_dung vì chúng ta không thể biết trước tên người dùng là gì?

Như vậy, biến số ngoài việc lưu giá trị còn để “xào nấu” dữ liệu. Giá trị trong biến có thể thay đổi. Ví dụ tiếp theo:

age = 30
print(age)

age = 40
print(age)

Kết quả chúng ta có số 30 in ra trước và đến dòng thứ 2 in ra số 40.

1.2 Cách đặt tên biến

Mỗi ngôn ngữ lập trình có quy ước bắt buộc hoặc một thói quen cộng đồng về việc quy chuẩn đặt tên khác nhau. Ví dụ có các kiểu đặt tên như:

  • underscore hay snake_case: sử dụng các dấu gạch dưới phân cách các từ trong tên biến. Ví dụ: ten_nguoi-dung, TI_LE_CHIET_KHAU
  • camelCase: viết hoa các chữ cái đầu tiên của từng từ trừ chữ cái từ đầu tiên. Ví dụ: tenNguoiDung
  • PascalCase: viết hoa tất cả các chữ cái đầu tiên của từng từ. Ví dụ: TenNguoiDung.

Trong Python, các kiểu đặt tên trên đều sử dụng được, tuy nhiên theo quy ước viết code chung của cộng đồng thì sử dụng kiểu gạch chân. Tên các biến sẽ được viết thường và tên hằng số được viết hoa.

# Tên biến trong Python
ten_nguoi_dung = "Nguyen Van A"
tuoi_nguoi_dung = 35

# Tên hằng số trong Python
SO_PI = 3.14159
KHACH_HANG_LA_THUONG_DE = true

Một số chú ý khi đặt tên biến trong Python:

  • Tên biến có thể chứa chữ số nhưng không được phép bắt đầu bằng chữ số.
  • Tên biến không được chứa các ký tự đặc biệt ngoài dấu gạch chân _.
  Những cải tiến đáng giá của Python 3.12
  Biến và kiểu dữ liệu cơ bản trong Python

2. Kiểu dữ liệu số trong Python

Kiểu dữ liệu số trong Python bao gồm hai loại là kiểu nguyên và kiểu thập phân. Trong một số các ngôn ngữ lập trình khác, kiểu nguyên hoặc kiểu thập phân còn được chi tiết hơn với khoảng rộng của dải số có thể (độ dài ô chứa số đó, ví dụ int và longint khác nhau). Python chỉ phân biệt số có và không có dấu chấm thập phân.

# Kiểu số nguyên - integer
tuoi_nguoi-dung = 35

# Kiểu số thập phân - float
ti_le_binh_chon = 8.2

3. Thực hiện phép toán trong Python

Trong Python chúng ta có thể thực hiện các phép toán đơn giản như +, -, *, / với quy tắc tính giống như ngoài thực tế là ưu tiên trong ngoặc trước, ngoài ngoặc sau, trong phép toán trước, ngoài phép toán sau (phép toán như khai căn, số mũ, logarit…), nhân chia trước, cộng trừ sau. Đây là các thứ tự thực hiện phép toán theo luật Pemdas, Bodmas.

Ví dụ thực hiện một phép tính trong Python:

maths_operation = 1 + 3 * 4 / 2 -2
print(maths_operation)

Kết quả nhận được là 5.0. Chú ý, kết quả của phép chia trong Python luôn trả về là một số thập phân dù phần thập phân có thể bằng 0.

4. Phép chia lấy phần nguyên và lấy phần dư trong Python

Trong ví dụ trên, nếu chúng ta muốn trả về là một số nguyên, trong Python chúng ta sẽ sử dụng toán tử // thay cho /. Toán tử này trả về phần nguyên của phép chia.

Ví dụ:

# Phép chia lấy phần nguyên
integer_division = 8 // 3
print(integer_division)

# Kết quả là 2 

Ngoài ra, Python cũng có toán tử % để lấy phần dư trong phép chia. Chúng ta có thể tính toán nếu biết phần nguyên nhưng sử dụng toán tử có sẵn sẽ thuận tiện hơn:

# Phép chia lấy phần dư
division_with_remainder = 13 // 5
print(division_with_remainder)

# Kết quả là 3 vì 13 chia 5 dư 3

Toán tử lấy phần dư phép chia có ứng dụng xác định một số là số chẵn hay số lẻ bằng cách kiểm tra phần dư trong phép chia cho 2 có kết quả là 0 hay 1. Vì số chẵn chia hết cho 2, số lẻ chia cho 2 dư 1. Kết quả này thường ứng dụng vào việc tô màu cho các dòng trong một bảng dữ liệu, giúp cho bảng dữ liệu dễ đọc hơn.

Bảng dữ liệu có phối màu nhờ xác định dòng chẵn lẻ

Như vậy chúng ta đã được giới thiệu về biến số là gì, cách đặt tên biến trong Python và kiểu dữ liệu đầu tiên là kiểu số (integer, float). Những kiến thức ban đầu rất cơ bản, bạn nào chưa bao giờ học lập trình nên đọc và thực hành kỹ bởi đây là nền tảng không chỉ học Python mà bất kỳ ngôn ngữ lập trình nào bạn sẽ tìm hiểu sau này.

5. Các phép toán phức tạp trong Python

Mặc định, Python hỗ trợ các phép toán thông thường để chúng ta tính toán, khi cần dùng đến các phép toán phức tạp hơn, chúng ta có thể sử dụng thư viện math. Để sử dụng thư viện này trong phần đầu của code chúng ta sử dụng lệnh import math để hệ thống tải thư viện này và chúng ta có thể sử dụng các hàm mà math cung cấp.

Ví dụ, có diện tích hình vuông ta muốn xác định cạnh của nó bằng hàm khai căn bậc 2 như sau:

import math

area_square = 64
square_edge = math.sqrt(area_square)
print(square_edge) # Kết quả là 8

Thư viện math còn có một số các hàm toán học hay sử dụng như sin, cos, log, pow (lũy thừa)…

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm tìm việc lập trình viên hấp dẫn trên TopDev

Function trong Python là gì? Tạo Function trong Python

Function trong Python là gì? Tạo Function trong Python

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Function trong Python là gì? Tạo Function trong Python

Function trong Python là gì?

Trong Python, function là một nhóm các câu lệnh (khối code) liên quan tới nhau, nhằm mục đích thực hiện một công việc nào đó.

Function giúp chia nhỏ chương trình thành các module nhỏ hơn. Chương trình càng lớn thì function càng nhiều.

Function giúp sử dụng lại các đoạn code. Tránh lặp lại các đoạn code trùng nhau.

Xem thêm việc làm python tuyển dụng từ các công ty lớn trên TopDev

Cú pháp của Function, cách tạo Function

Cấu trúc function:

def function_name ( arg1, arg2, ...) : 
 ...... 
# function body 
 ......
  • Từ khóa def đánh dấu bắt đầu function header
  • Tên của một function phải là duy nhất
  • Dấu hai chấm : đánh dấu kết thúc function header
  • Phần body mô tả công việc của function
  • Các function có thể có từ khóa return để trả về một kết quả sau khi function xử lý.

Ví dụ:

def subtract(a, b):
return (a-b)

def say_hello():
print("Hello World")

Gọi function: để gọi một function ta viết tên và các tham số của nó.

say_hello()
print("10 - 5 = %d" % subtract(10, 5)) # prints -2

Kết quả:

Hello World
10 - 5 = 5
  Python Lists: Append vs Extend (Có ví dụ)

Phạm vi và vòng đời của biến trong function

Các biến trong function chỉ có giá trị bên trong function (biến local). Sau khi function kết thúc, chúng bị hủy đi.

Ví dụ:

def my_func():
 x = 10
print("Value inside function:",x)

x = 20
my_func()
print("Value outside function:",x)

Kết quả:

Value inside function: 10
Value outside function: 20

Okay, Done!

  Vẽ đồ thị trong Python với thư viện Matplotlib

References: https://docs.python.org/2.0/ref/function.html

Bài viết gốc được đăng tải tại codecute.com

Xem thêm IT tuyển dụng từ các công ty lớn trên TopDev

Lý thuyết toán ma trận sử dụng trong các thuật toán Machine Learning

Lý thuyết toán ma trận sử dụng trong các thuật toán Machine Learning

Bài viết được sự cho phép của tác giả Kien Dang Chung

Machine learning là một tập hợp rất nhiều các thuật toán khác nhau và nó có liên hệ rất mật thiết với toán học, đặc biệt là toán cao cấp. Chúng ta ai đã mài đũng quần trên giảng đường đại học đều không còn xa lạ với Đại số tuyến tính và đây cũng là kiến thức nền tảng của rất nhiều các thuật toán sẽ được giới thiệu trong Machine Learning.

  9 hiểu lầm "ngớ ngẩn" về machine learning
  Chia sẻ cơ bản sử dụng machine learning để giải quyết bài toán.

1. Một số khái niệm cơ bản

1.1 Vô hướng (Scalar)

Scalar (mathematics), an element of a field, which is used to define a vector space, usually the field of real numbers

Một đại lượng vô hướng là một phần tử của một trường được sử dụng để xác định một không gian vector, thông thường ở đây là trường số thực.

Wiki

Tóm lại đại lượng vô hướng (Scalar) là một số bất kì thuộc tập số nào đó. Khi định nghĩa một số ta phải chỉ rõ tập số mà nó thuộc vào. Ví dụ, nn là số tự nhiên sẽ được kí hiệu: nNn∈N, hoặc rr là số thực sẽ được kí hiệu: rRr∈R. Một số thường có thể định nghĩa được bằng một kiểu dữ liệu nguyên thủy của các ngôn ngữ lập trình. Như số tự nhiên có thể là kiểu int, số thực có thể là kiểu float trong Python.

1.2 Véc tơ (Vector)

Vector là 1 mảng của các đại lượng vô hướng tương tự như mảng 1 chiều trong các ngôn ngữ lập trình. Các phần tử trong vector được đánh địa chỉ và có thể truy cập nó qua các địa chỉ tương ứng của nó. Trong toán học, một vector có thể là vector cột nếu các nó được biểu diễn dạng cột, hoặc có thể là vector hàng nếu nó được biểu diễn dưới dạng cột của các phần tử.

Một véc-tơ cột có dạng như sau:

x=⎡⎣⎢⎢⎢⎢x1x2xn⎤⎦⎥⎥⎥⎥x=[x1x2⋮xn]


Một véc-tơ hàng có dạng như sau:

x=[x1x2xn]x=[x1x2⋯xn]

Trong đó, x1x1x2x2, …, xnxn là các phần tử thứ 1, thứ 2, … thứ n của vector.

1.3 Ma trận (Matrix)

Ma trận trên trường K là một bảng liệt kê các số như: số thực, số phức hay một hàm số,… được sắp xếp theo một trật tự nhất định gốm có m dòng và n cột

A=⎡⎣⎢⎢⎢⎢⎢a11a21am1a12a22am2a1na2namn⎤⎦⎥⎥⎥⎥⎥A=[a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮am1am2⋯amn]

Trong đó aijaij là phần tử dòng i cột j, phần tử này có thể là số thực hoặc số phức. Ma trận này được ký hiệu là A=(aij)mxnRm×nA=(aij)mxn∈Rm×n

Như vậy véc tơ là trường hợp đặc biệt của ma trận:

  • m = 1 chúng ta có ma trận A=(aij)1xnA=(aij)1xn là véc tơ hàng.
  • n = 1 chúng ta có ma trận A=(aij)mx1A=(aij)mx1 là véc tơ cột.

Ma trận tương ứng với mảng 2 chiều trong các ngôn ngữ lập trình. Véc tơ tương ứng với mảng 1 chiều.

1.4 Ten-xơ (Tensor)

Ten-xơ là một mảng đa chiều, nó là trường hợp tổng quát khi biểu diễn trường số đa chiều. Như vậy, ma trận, véc tơ và vô hướng chỉ là những trường hợp cụ thể của ten-xơ:

  • Ma trận là ten-xơ 2 chiều.
  • Véc tơ là ten-xơ 1 chiều.
  • Vô hướng là ten-xơ 0 chiều.

Các phần tử trong ten-xơ được xác định bằng các chỉ số trên từng chiều của ten-xơ, ví dụ một ten-xơ 3 chiều A=(aijk)mxnxpA=(aijk)mxnxp khi đó phần tử aijkaijk sẽ ở hàng i, cột j và mặt phẳng k.

Tìm ngay việc làm Machine Learning tại TopDev!

2. Một số ma trận đặc biệt

2.1 Ma trận không

Ma trận không là ma trận mà các phần tử bên trong đều bằng 0, aij=0,i,jaij=0,∀i,j. Ma trận không được ký hiệu là 

=⎡⎣⎢⎢⎢⎢⎢000000000⎤⎦⎥⎥⎥⎥⎥∅=[00⋯000⋯0⋮⋮⋱⋮00⋯0]

2.2 Ma trận đơn vị

Ma trận đơn vị là ma trận vuông có các phần tử trên đường chéo từ bên trên tay trái xuống bên dưới tay phải bằng 1, còn các phần tử khác bằng 0. Ma trận đơn vị thường được ký hiệu là InIn trong đó nn là số hàng và số cột của ma trận:

{aij=0,ijaij=1,i=j{aij=0,∀i≠jaij=1,∀i=j

In=⎡⎣⎢⎢⎢⎢⎢100010001⎤⎦⎥⎥⎥⎥⎥In=[10⋯001⋯0⋮⋮⋱⋮00⋯1]

2.3 Ma trận vuông

Ma trận vuông là ma trận có số hàng bằng với số cột A=(aij)n×nA=(aij)n×naijRn×naij∈Rn×n. Trong ma trận vuông, đường chéo từ trên bên trái xuống dưới bên phải được gọi là đường chéo chính {aij}i=j{aij}∀i=j.

Ví dụ một ma trận vuông:

A=⎡⎣⎢132309255⎤⎦⎥A=[13−2−305−295]

2.4 Ma trận nghịch đảo

Cho một ma trận vuông A=(aij)n×nRn×nA=(aij)n×n∈Rn×n, nếu có ma trận B=(bij)n×nRn×nB=(bij)n×n∈Rn×n sao cho A×B=InA×B=In với InIn là ma trận đơn vị có kích thước nn thì ta nói rằng:

  • Ma trận AA là khả nghịch.
  • Ma trận BB là ma trận nghịch đảo của AA và được thường ký hiệu là A1A−1

Ma trận nghịch đảo thường được sử dụng để tìm lời giải cho phương trình tuyến tính dạng A×x=BA×x=B với A=(aij)n×nRn×nA=(aij)n×n∈Rn×nx=[x1x2...xn]x=[x1x2…xn] và B=(bij)n=[b1b2...bn]RnB=(bij)n=[b1b2…bn]∈Rn.

Phương trình tuyến tính này có thể viết dưới dạng chi tiết như sau:

⎧⎩⎨⎪⎪⎪⎪⎪⎪a11x1+a12x2+...+a1nxn=b1a21x1+a22x2+...+a2nxn=b2...an1x1+an2x2+...+annxn=bn{a11x1+a12x2+...+a1nxn=b1a21x1+a22x2+...+a2nxn=b2...an1x1+an2x2+...+annxn=bn

Để giải phương trình này ta chỉ cần tìm ma trận nghịch đảo A1A−1, thật vậy:

A1×A×x=A1×Bx=A1×BA−1×A×x=A−1×B⇒x=A−1×B

2.5 Ma trận chuyển vị

Ma trận chuyển vị, ký hiệu ATAT là ma trận được thành lập từ ma trận ban đầu bằng cách chuyển dòng thành cột và ngược lại:

AT=⎡⎣⎢⎢⎢⎢⎢a11a21an1a12a22am2a1ma2manm⎤⎦⎥⎥⎥⎥⎥AT=[a11a12⋯a1ma21a22⋯a2m⋮⋮⋱⋮an1am2⋯anm]

Chú ý: Đôi khi, người ta định nghĩa véc tơ cột từ véc tơ dòng như sau:

x=[x1,x2,,xn]x=[x1,x2,…,xn]⊺

Ma trận đối xứng:

Nếu một ma trận bằng chính ma trận chuyển vị của nó thì ma trận đó được gọi là ma trận đối xứng.

A=AA=A⊺ thì AA được gọi là ma trận đối xứng.

2.6 Ma trận liên hợp

Nếu ma trận A=(aij)m×nA=(aij)m×naijCm×naij∈Cm×n có các phần tử là số phức thì khi vừa thực hiện chuyển đổi hàng thành cột và lấy liên hợp phức các phần tử chúng ta được ma trận liên hợp Hermitian, được ký hiệu là AHAH.

Nói cách khác, ta có ma trận A=(aij)m×nA=(aij)m×naijCaij∈C thì ma trận B=(bij)n×mB=(bij)n×mbijCbij∈C là ma trận liên hợp phức nếu:

bij=aji¯¯¯¯¯¯,i=1,n¯¯¯¯¯¯¯¯,j=1,m¯¯¯¯¯¯¯¯¯bij=aji¯,∀i=1,n¯,j=1,m¯

Ví dụ, ta có ma trận sau:

A=[12i23+4ii]A=[1−2i3+4i2−i]

thì ma trận liên hợp phức của A sẽ là:

AH=[1+2i34i2i]AH=[1+2i23−4ii]

Khi AA là ma trận số thực (ARm×nA∈Rm×n) thì ta có AH=AAH=A⊺.

Ma trận Hermitian:

Nếu ma trận A=(aij)m×nCm×nA=(aij)m×n∈Cm×n thì ma trận A được gọi là ma trận Hermitian nếu AH=AAH=A.

3. Các phép toán với ma trận

3.1 Nhân ma trận với một số

Nhân ma trận với một số (vô hướng) là cách thực hiện phép nhân từng phần tử của ma trận với số đó.

α×A=(α×aij)m×nα×A=(α×aij)m×n

α×A=⎡⎣⎢⎢⎢⎢⎢α×a11α×a21α×an1α×a12α×a22α×am2α×a1mα×a2mα×anm⎤⎦⎥⎥⎥⎥⎥α×A=[α×a11α×a12⋯α×a1mα×a21α×a22⋯α×a2m⋮⋮⋱⋮α×an1α×am2⋯α×anm]

Nhân ma trận với một số có những tính chất như sau:

  • Giao hoán: α×A=A×αα×A=A×α
  • Tính chất kết hợp: α(βA)=(αβ)Aα(βA)=(αβ)A
  • Tính chất phân phối: (α+β)A=αA+βA(α+β)A=αA+βA

Ví dụ:

A=⎡⎣⎢⎢⎢5703328061219535⎤⎦⎥⎥⎥A=[536−9−72150−82−33015]

Thì:

2×A=⎡⎣⎢⎢⎢⎢2×52×(7)2×02×32×32×22×(8)2×02×62×12×22×12×(9)2×52×(3)2×5⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢10140664160122421810610⎤⎦⎥⎥⎥2×A=[2×52×32×62×(−9)2×(−7)2×22×12×52×02×(−8)2×22×(−3)2×32×02×12×5]=[10612−18−1442100−164−660210]

3.2 Phép cộng hai ma trận

Phép cộng hai trận chỉ thực hiện được khi cùng cấp, ví dụ A=(aij)m×nA=(aij)m×n có thể cộng với B=(bij)m×nB=(bij)m×n:

A+B=(aij)m×n+(bij)m×n=(aij+bij)m×nA+B=(aij)m×n+(bij)m×n=(aij+bij)m×n

Viết một cách chi tiết như sau:

A+B=⎡⎣⎢⎢⎢⎢⎢a11a21am1a12a22am2a1na2namn⎤⎦⎥⎥⎥⎥⎥+⎡⎣⎢⎢⎢⎢⎢b11b21bm1b12b22bm2b1nb2nbmn⎤⎦⎥⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢⎢a11+b11a21+b21am1+bm1a12+b12a22+b22am2+bm2a1n+b1na2n+b2namn+bmn⎤⎦⎥⎥⎥⎥⎥A+B=[a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮am1am2⋯amn]+[b11b12⋯b1nb21b22⋯b2n⋮⋮⋱⋮bm1bm2⋯bmn]=[a11+b11a12+b12⋯a1n+b1na21+b21a22+b22⋯a2n+b2n⋮⋮⋱⋮am1+bm1am2+bm2⋯amn+bmn]

Phép cộng hai ma trận có một số tính chất như sau:

  • Cộng với ma trận không bằng chính nó: A+=AA+∅=A
  • Tính giao hoán: A+B=B+AA+B=B+A
  • Tính kết hợp: A+(B+C)=(A+B)+CA+(B+C)=(A+B)+C
  • Tính phân phối: α(A+B)=αA+αBα(A+B)=αA+αB

3.3 Phép nhân hai ma trận

Cho hai ma trận A=(aij)m×nA=(aij)m×n và B=(bij)n×pB=(bij)n×p. Phép nhân hai ma trận cho kết quả là một ma trận C=(cij)m×pC=(cij)m×p với:

cij=k=1naik×bkj,i=1,m¯¯¯¯¯¯¯¯¯;j=1,p¯¯¯¯¯¯¯cij=∑k=1naik×bkj,∀i=1,m¯;j=1,p¯

Chú ý: Để nhân được hai ma trận thì số cột của ma trận thứ nhất phải bằng số hàng của ma trận thứ hai trong phép nhân.\

Một số tính chất của phép nhân hai ma trận:

  • Nhân ma trận với ma trận đơn vị không làm thay đổi ma trận đó: A×I=AA×I=A
  • Không có tính chất giao hoán trong phép nhân: A×BB×AA×B≠B×A, trong nhiều trường hợp phép nhân B×AB×A còn không tồn tại do số cột của B khác số hàng của A.
  • Tính kết hợp: A×(B×C)=(A×B)×CA×(B×C)=(A×B)×C.
  • Tính phân phối: A×(B+C)=A×B+A×CA×(B+C)=A×B+A×C và (A+B)×C=A×C+B×C(A+B)×C=A×C+B×C.
  • Chuyển vị của một tích bằng tích các chuyển vị theo thứ tự ngược lại: (A×B)=B×A(A×B)⊺=B⊺×A⊺.
  • Liên hợp phức của một tích bằng tích các liên hợp phức theo thứ tự ngược lại: (A×B)H=BH×AH(A×B)H=BH×AH.

4. Giải tích ma trận

4.1 Hàm đa biến số

Như chúng ta đã biết các phương trình đường thẳng y=ax+by=ax+b (có thể viết dạng ax+by+c=0ax+by+c=0) hay phương trình mặt phẳng ax+by+cz+d=0ax+by+cz+d=0. Tổng quát hóa, một siêu mặt phẳng trong không gian n chiều có phương trình như sau:

a1x1+a2x2+...+anxn+a0=0a1x1+a2x2+…+anxn+a0=0

Hàm số đa biến số là một hàm phụ thuộc vào nhiều biến số f(x):RnRf(x):Rn→R. Viết một các chi tiết hơn:

(x1,x2,...,xn)f(x1,x2,...,xn)R(x1,x2,…,xn)→f(x1,x2,…,xn)∈R

Ví dụ, z=x2+y2z=x2+y2 là một hàm số của biến x,yx,y.

Trong machine learning, các vấn đề chúng ta gặp phải không chỉ có đầu ra là một số (vô hướng) mà có thể là một vector, tổng quát hơn có thể là ma trận hoặc tensor. Do đó hàm số đa biến sẽ ở dạng tổng quát hơn, còn gọi là hàm véc tơ như sau:

f(x):RnRmf(x):Rn→Rm

Ví dụ một hàm vector có ba biến số như sau f(x,y,z):R3R2f(x,y,z):R3→R2:

f(x,y,z)=[x2+sin(y)+xzcos(x)+y2z]f(x,y,z)=[x2+sin(y)+xzcos(x)+y2z]

4.2 Đạo hàm riêng

Đạo hàm riêng của một hàm nhiều biến số là đạo hàm theo biến số đó với giả thuyết các biến số khác là hằng số. Ký hiệu fx(x0,y0)fx′(x0,y0) hoặc f(x0,y0)x∂f(x0,y0)∂x, đây là đạo hàm riêng theo biến xx, còn đạo riêng theo biến yy sẽ viết như sau: fy(x0,y0)fy′(x0,y0) hoặc f(x0,y0)y∂f(x0,y0)∂y.

Ví dụ: với hàm số ở phần trên ta có đạo hàm riêng theo các biến x,y,zx,y,z như sau:

f(x,y,z)x=[2x+zsin(x)]f(x,y,z)x′=[2x+z−sin(x)]

f(x,y,z)y=[cos(y)2yz]f(x,y,z)y′=[cos(y)2yz]

f(x,y,z)z=[xy2]

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm Việc làm Machine Learning hấp dẫn trên TopDev

Tuple comprehension

Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng

Python có sẵn (builtin) 4 kiểu dữ liệu “compound”/”container” quan trọng, chúng dùng để chứa các giá trị. listtuplesetdict.

Một lập trình viên Python phải nắm thành thạo cả 4 kiểu dữ liệu trên và vận dụng linh hoạt, biết điểm mạnh yếu của từng kiểu. Bàn về chuyện ấy lại cần vài bài dài dòng khác nên sẽ giữ lại “để sau”/”lúc nào rảnh”.

  10 sự thật thú vị về ngôn ngữ lập trình Python
  11 tip học Python dành cho các “newbie”

Comprehension

Comprehension là một đặc sản của Python, một khi biết đến là hay bị nghiện, thứ cú pháp ngắn gọn sạch sẽ ngọt như mía lùi cũng chính là vũ khí giết những con ong ham ăn.

Cú pháp này Python “vay mượn” mà không bao giờ trả từ Haskell – một ngôn ngữ vốn có tiếng khó học và vi diệu. Hãy thử xem 2 ví dụ sau:

In [1]: names = ['vuong', 'tron', 'tam giac']

In [2]: more_than_four_chars = []

In [3]: for name in names:
   ...:     if len(name) > 4:
   ...:         more_than_four_chars.append(name.title())
   ...:

In [4]: print(more_than_four_chars)
['Vuong', 'Tam Giac']

4 dòng code (dòng print không tính) trên để ta filter (lọc) từ một tập hợp đã cho, thu về các phần tử thỏa mãn điều kiện (hơn 4 ký tự) rồi map (biến đổi) các ký tự đứng đầu thành chữ hoa.

Dù đẹp sạch dễ hiểu lắm rồi, nhưng so với list comprehension:

In [5]: names = ['vuong', 'tron', 'tam giac']

In [6]: print([name.title() for name in names if len(name) > 4])
['Vuong', 'Tam Giac']

thì sự ngắn gọn, đơn giản này đánh bại hoàn toàn cú pháp thông thường.

Và ta còn làm tương tự được với setdict:

In [9]: {i for i in [1,2,3,4,1,2] if i % 2 == 0}
Out[9]: {2, 4}

In [10]: {i: i**2 for i in range(5,10) if i % 2 == 1}
Out[10]: {5: 25, 7: 49, 9: 81}

Tuple comprehension

Dễ tưởng tượng ra là ta sẽ có luôn tuple comprehension – vì nghe có vẻ hợp lý mà:

In [13]: type((i for i in range(5,10) if i % 2 == 0))
Out[13]: <class 'generator'>

SAI! khái niệm tuple comprehension không tồn tại. Cùng cú pháp nhưng kết quả thu được là 1 generator.

Vì sao thế?

Tuple được tạo ra, ban đầu trông như 1 phiên bản thiếu tính năng của list, nhưng mục đích tạo ra tuple là hoàn toàn khác. tuple được dùng như khái niệm struct trong các ngôn ngữ khác, nó là tập hợp của các thông tin khác nhau:

In [14]: student = ('Meo', 18, '0699609096', 'PyMi.vn')

và khi dùng thì unpack các giá trị ra:

In [15]: name, age, phone, school = student

In [16]: print(school)
PyMi.vn

Còn list dùng để lặp qua/ duyệt qua:

In [17]: names = ['vuong', 'tron', 'tam giac']

In [18]: for name in names:
    ...:     print('Hello các bạn mình là {}'.format(name.title()))
    ...:
Hello các bạn mình  Vuong
Hello các bạn mình  Tron
Hello các bạn mình  Tam Giac

Xem thêm tại FAQ của Python.

Ok, vậy chẳng có nghĩa lý gì để “comprehension” ra tuple cả.

Lập trình viên phê list comprehension túy lúy!

Đã dùng là nghiện, mà nghiện là rất khó tỉnh. List comprehension hấp dẫn vậy nên thường bị dùng SAI, lạm dụng. Một điều duy nhất quan trọng cần nhớ:

List comprehension là để tạo ra list.

Thế nhưng không ít lần, nó bị lạm dụng, khi người ta không cần đến list:

  • khi chỉ cần đếm “số lượng phần tử”
  • để tính tổng
  • để in ra màn hình
  • để viết những vòng lặp điều kiện phức tạp.

List comprehension tạo ra 1 list, vậy nên nếu không cần tới list kết quả đó thì không nên dùng tới list comprehension mà hãy dùng vòng lặp for thông thường:

Đừng viết:

In [19]: [print(name.upper()) for name in names]
VUONG
TRON
TAM GIAC
Out[19]: [None, None, None]

Hãy viết:

In [20]: for name in names:
    ...:     print(name.upper())
    ...:
VUONG
TRON
TAM GIAC

Ta không tạo ra 1 cái list vô nghĩa chứa 3 phần tử None – tức là tiết kiệm bộ nhớ (memory).

Đừng viết:

In [21]: len([i for i in range(100,1000) if i % 2 == 0])
Out[21]: 450

Hãy viết:

In [22]: c = 0

In [23]: for i in range(100, 1000):
    ...:     if i % 2 == 0:
    ...:         c = c + 1
    ...:

In [24]: print(c)
450

vì ta sẽ không tạo ra 1 list (tạm) chứa 450 phần tử.

Và đừng viết:

In [25]: sum([i for i in range(5000000)])
Out[25]: 12499997500000

Mà hãy viết:

In [26]: sum_zero_to_5mil = 0

In [27]: for i in range(5000000):
    ...:     sum_zero_to_5mil = sum_zero_to_5mil + i
    ...:

In [28]: sum_zero_to_5mil
Out[28]: 12499997500000

bởi ta sẽ không vô tình tạo ra một list chiếm tới ~180MB bộ nhớ chỉ để tính tổng.

Cách tính

In [32]: import sys

In [33]: list_size =  sys.getsizeof([i for i in range(5000000)])

In [34]: all_numbers_size = sys.getsizeof(5000000) * 5000000

In [35]: print(list_size, all_numbers_size, list_size + all_numbers_size)
40215168 140000000 180215168

Và nếu như số vòng for hay lệnh if trong list comprehension nhiều hơn 2,3 nó không còn sạch sẽ và dễ đọc nữa, hãy quay trở về dùng vòng lặp for thông thường. Ở CIA họ dạy thế.

List/set/dict comprehension rất tiện để tạo list/set/dict, nhưng khi không cần tới list/set/dict kết quả, hãy đừng lạm dụng.

Generator

Generator sinh ra các phần tử của list tương ứng, nhưng mỗi lần, chỉ có 1 phần tử được tạo ra, vì vậy thường dùng để tiết kiệm RAM. Cú pháp tạo generator đơn giản chỉ là thay dấu [] thành ().

In [36]: sys.getsizeof([i for i in range(5000000) if i % 3 == 0 or i % 5 == 0])
Out[36]: 19836760

In [37]: sys.getsizeof((i for i in range(5000000) if i % 3 == 0 or i % 5 == 0))
Out[37]: 88

In [38]: sum([i for i in range(5000000) if i % 3 == 0 or i % 5 == 0])
Out[38]: 5833329166668

In [39]: sum(i for i in range(5000000) if i % 3 == 0 or i % 5 == 0) # chỗ này mượn tạm luôn dấu () của sum
Out[39]: 5833329166668

Đã đến lúc lạm dụng generator!!! nó được dùng mọi nơi trong Python3 và là một cải tiến hấp dẫn của Python3 so với Python2.

Hết.

Bài viết gốc được đăng tải tại pp.pymi.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Ngôn ngữ C là gì? Code ví dụ Hello World

Ngôn ngữ C là gì? Code ví dụ Hello World

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Ngôn ngữ C là gì? Code ví dụ Hello World

1. Ngôn ngữ lập trình C là gì?

C là một ngôn ngữ lập trình máy tính. Được dùng để tạo ra các chỉ dẫn cho máy tính.

C được phát triển bởi Dennis M. Ritchie để phát triển hệ điều hành UNIX sau đó được sử dụng để phát triển các phần mềm…

C có thể chạy trên hầu hết các hệ điều hành.

C được coi như là ngôn ngữ mẹ vì nó được dùng để viết ra nhiều ngôn ngữ khác như C++, Python, Java

C được đánh giá là dễ học so với các ngôn ngữ bậc thấp như Assembly hay Pascal… Do đó nó được sử dụng làm môn lập trình cơ sở (Hiện tại một số trường đại học đã chuyển môn cơ sở sang Javascript). Tuy nhiên so với các ngôn ngữ bậc cao như Java, Python thì nó lại khó học hơn rất nhiều.

Tham khảo việc làm lập trình viên C/C++ lương cao trên TopDev

C là một ngôn ngữ bậc trung, được sử dụng để:

  • Kết hợp với Assembly để viết các trình điều khiển
  • Viết hệ điều hành
  • Viết ra các ngôn ngữ khác
  • Sử dụng để viết các hệ thống core

Nhìn chung thì C khá là khó (bởi khái niệm con trỏ, quản lý bộ nhớ) và thường trên trường chỉ học ở mức độ cơ bản. Nếu theo lập trình về phần cứng, hệ điều hành hay các hệ thống core thì mới tiếp tục học nâng cao… do đó mới đầu học C các bạn thấy khó nhằn một chút thì cũng bình thường.

  Kiến thức C cho người mới và cách tự học lập trình C

2. Code ví dụ C – Hello World

Ví dụ in ra dòng chữ ‘Hello World’ bằng ngôn ngữ lập trình C.

Tạo file Hello.c với nội dung sau:

#include <stdio.h>

int main() {
printf("Hello World!");
return 0;
}

(Các file viết bằng ngôn ngữ c có đuôi mở rộng là .c)

  • #include <stdio.h> khai báo file stdio.h, nó là một thư viện mà ta có thể dùng sẵn. Trong trường hợp này hàm printf() mà mình sử dụng đã được định nghĩa trong sdtio.h, nếu mình không khai báo stdio.h thì chương trình sẽ không hiểu hàm printf() là gì.
  • int main() hàm main (chương trình viết bởi c sẽ bắt đầu chạy từ hàm main). int biểu thị kết quả trả về của hàm main là kiểu số nguyên
  • Các dấu {} được dùng để đánh dấu mở đầu và kết thúc của một khối lệnh, một hàm. Dấu ; được dùng để kết thúc 1 lệnh
  • printf("Hello World!"); thực hiện in ra dòng chữ Hello World!
  • return 0; kết quả trả về của hàm main là 0. Trong ví dụ này thì giá trị trả về của hàm main không quan trọng (mình sẽ nói rõ về phần này sau)
  Các từ khóa/key words trong ngôn ngữ C/C++

Chạy file Hello.c

File Hello.c được viết bằng ngôn ngữ C. Do đó để chạy được file Hello.c ta phải biên dịch nó thành mã máy (file .exe) để chạy.

Để biên dịch được các file viết bằng ngôn ngữ C ta cần cài đặt trình biên dịch (complier) cho ngôn ngữ C.

Nếu bạn đang sử dụng linux thì không cần cài đặt thêm vì linux viết bằng C nên nó đã tích hợp sẵn trình biên dịch C.

Trường hợp bạn sử dụng Windows thì phải cài thêm trình biên dịch C như MinGW, Cygwin…

Ngôn ngữ lập trình C là gì? Ví dụ Hello

Mình sử dụng Windows và đã cài trình compiler MinGW.

Thực hiện compile file Hello.c thành file .exe

Ví dụ file Hello.c mình để ở folder D:\programming, mình sẽ mở màn hình cmd, di chuyển tới folder D:\programming

Ngôn ngữ C là gì? Code ví dụ Hello World

Chạy lệnh gcc Hello.c -o hello.exe để build (biên dịch/compile) file Hello.c thành file hello.exe

Ngôn ngữ C là gì? Code ví dụ Hello World

Chạy file hello.exe vừa tạo ra ta sẽ thấy in ra dòng chữ Hello World! trên màn hình.

Ngôn ngữ C là gì? Code ví dụ Hello World

Okay! Done!

Bài viết gốc được đăng tải tại codecute.com

Có thể bạn quan tâm:

Xem thêm Việc làm ngành it hấp dẫn trên TopDev