FizzBuzz: nấc thang lên thiên đường của lập trình viên

TDD: Test Driven Development (Tạm hiểu là phương pháp lập trình bằng cách viết Unit Test trước khi code)
Refactoring Code (Tạm hiểu là dọn dẹp mã nguồn lại cho trong sáng, dễ hiểu, không dư thừa, …)

2 Likes

Code của mình thì thế này (Python):

   for i in range(1,101):
    out = ""
    if i % 3 == 0:
    out += "Fizz"
    if i % 5 == 0:
    out += "Buzz"
    if out == "":
    out = str(i)
    print out

Đại khái để đảm bảo cho 1 vài yếu tố là không lặp điều kiện, dễ đọc, dễ hiểu.

Còn có lẽ cách này là để tối ưu code :smiley:

1 Like

@ECHO OFF
SET /a i=0
:loop
SET /a i= i+1
SET /a test=%i% %% 3
SET /a test1=%i% %% 5
IF %test% EQU 0 (GOTO :Fizz) ELSE (GOTO Buzz)
:point
IF %i%==100 (PAUSE) ELSE (GOTO loop)
:Buzz
IF %test1% EQU 0 (ECHO Buzz) ELSE (ECHO %i%)
GOTO point
:Fizz
IF %test1% EQU 0 (ECHO FizzBuzz) ELSE (ECHO Fizz)
GOTO point

Cách phía dưới của Đạt cũng chưa phải là một giải pháp tốt vì nó chưa mang tính tổng quan. Vì nếu như có sự thay đổi về yêu cầu (ko phải là 3 và 5 hoặc thay đổi luôn cả chữ Fizz và Buzz) thì việc modify lại các giá trị này trực tiếp vào code là điều nên tránh. Vì vây nên viết ra một function mang tính tổng quan hơn, bao gồm input là 2 biến dạng Map(int , String ) và giá trị trả về sẽ là một String.

Java : 
public static String doFizzBuzz(Map<int, String> map1, Map<int, String> map2){
}

Sử dụng:

String s = doFizzBuzz(new HashMap< 3, “Fizz”>, new HashMap< 5, “Buzz”) );

Gần giống bài đầu tiên của Euler Project :slight_smile:

Em là người mới chẳng biết tí nào về lập trình . Các anh có thể xác định hướng học giúp em với được không ạ ! Thân!

Mình muốn đề xuất cách này, tuy nhìn có vẻ dài và phức tạp nhưng lại rất tường minh và dễ hiểu.
Mình thì muốn tránh xử dụng biến nên mình sẽ viết tất cả theo hàm và dùng đệ quy thay cho vòng lặp.
Ở đây mình tạo 1 kiểu dữ liệu uỷ thác là MyWay, bằng cách này khi gọi hàm viết ra dãy số mình có thể ghi rõ là mình chọn cách ghi ra dãy số thế nào, ở đây là mình chọn cách FizzBuzzWay nên mình khởi tạo 1 thể hiện của kiểu dữ liệu uỷ thác đã tạo tham chiếu tới phương thức FizzBuzzWay. Nếu không thích viết ra màn hình theo cách FizzBuzzWay này, mình có thể dễ dàng thay thế bằng 1 cách viết ra màn hình khác, chẳng hạn trong bài mình bịa ra 1 cách mới gọi là BoomWay. Bạn cũng có thể tuỳ ý tạo ra cách của bạn.
Mình đang học lập trình hàm và mình thấy cách này tường minh và dễ hiểu hơn rất nhiều so với cách làm thủ tục ở trên.
Mời các bạn góp ý.
Xin biện minh lại nếu các bạn nói mình viết quá dài cho 1 bài toán đơn giản, mình chỉ muốn bài toán này khi người đọc đọc sẽ hiểu ý của mình nhanh nhất, họ nhìn vào chương trình chính và thấy ngay ý định của mình khi mình gọi hàm ShowArray, ở đây họ sẽ thấy ngay là: à, cậu ta muốn in 1 dãy từ 1 đến 20 ra màn hình theo kiểu FizzBuzz đây.
class Program
{
public delegate string MyWay(int x);
public static string FizzBuzzWay(int x)
{
if (((x % 3) == 0) && ((x % 5) == 0)) return “FizzBuzz”;
if ((x % 3) == 0) return “Fizz”;
if ((x % 5) == 0) return “Buzz”;
return x.ToString();
}
public static string BoomWay(int x)
{
if (((x % 3) == 0) && ((x % 5) == 0)) return “BoomMoob”;
if ((x % 3) == 0) return “Boom”;
if ((x % 5) == 0) return “Moob”;
return x.ToString();
}
public static void ShowArray(MyWay way, int x, int y)
{
if (x <= y)
{
Console.WriteLine(way(x));
ShowArray(way, x + 1, y);
}
}
static void Main(string[] args)
{
MyWay way = new MyWay(FizzBuzzWay);
ShowArray(way, 1, 20);
Console.ReadKey();
}
}

Không, mình chẳng thấy tường minh gì cả =)) chắc cũng chẳng ai thấy tường minh đâu :))

1 Like

Ko phải cái gì cũng cần viết thành hàm và phải viết thành hàm
Và FizzBuzz là để viết trong 10 phút

1 Like

Các bạn không hiểu ý mình rồi =)) ai chẳng biết là bài này dễ, viết kiểu gì cũng được. Nhưng chủ ý của mình khi viết thành hàm thế kia là muốn làm nó theo hướng lập trình hàm, nghĩ là tập chung vào việc xử lý đầu vào và đầu ra của chúng ta. Ở đây là mình dùng hàm ShowArray theo cú pháp ShowArray(cách mà bạn muốn in ra, đầu vào, đầu ra). Có nghĩa là bạn không cần tập trung vào là máy nó sẽ tính toán thế nào, mình chỉ cần biết là “mày in cho tao cái hàm này ra, theo kiểu Fizz Buzz”. Chúng ta hoàn toàn có thể viết theo hướng thủ tục như ở trên, nhưng cách đó thì lại mang tư tưởng lập trình thủ tục, mình không thích kiểu đó.
Cơ mà thôi, cảm giác giống gây war quá :)) Chỉ là 1 sở thích nhỏ trong 1 bài toán đơn giản thôi mà :))))

Đây là một ý kiến mà mình rất đồng tình, có thể bạn không thấy nó chính xác, nhưng mà mình rất vui nếu bạn cũng đọc :))

http://tek.eten.vn/tim-hieu-ve-bieu-thuc-lambda

Mình viết code trên dựa trên tư tưởng theo cái bài này này :))

:)) nói chung là vẽ rắn thêm chân thì vẫn là vẽ rắn thêm chân thôi. Dùng FizzBuzz để luyện tập thì được, chứ đừng nói cái gì mà tường mình hơn với cả thấy ngay là :)) nghe buồn cười lắm.

Btw đây là bài mình viết về xem xét FizzBuzz dưới góc nhìn Machine Learning.
https://daynhauhoc.com/t/giai-quyet-bai-toan-fizzbuzz-bang-machine-learning-su-dung-tensorflow/43695

1 Like

@Tulip Mình không thích cách trả lời của bạn. Bạn nói người khác không nên tỏ ra hơn người, nhưng chính bạn lại dùng giọng điệu đó để thể hiện điều bạn muốn nói. Bạn cứ coi đây là 1 cmt gây war nếu bạn muốn.
Mình sẽ không cmt thêm bất kỳ 1 cmt nào trong post này nữa, thế nên mong bạn hãy chỉnh sửa lại cách nhìn nhận về quan điểm của người khác của bạn.

Oh tiếc ghê bạn không cmt thêm trong bài này nữa. Bạn nói hợp lý, mình cũng không thích cách cmt của bạn, vậy là hoà rồi nha. Trời ơi, gì mà cmt gây war chứ, hàng ngày mình nói chuyện với đồng nghiệp còn căng hơn à.

Với cả, ơ kìa, mình có bảo rằng không nên tỏ ra hơn người đâu, hơn người thì bảo hơn ngừoi, kém người thì bảo kém người. Perelman năm 23 tuổi đã tự tin bản thân là nhà hình học giỏi nhất thế giới, và vài năm sau hắn tỏ ra giận dữ nếu người ta không nhận ra điều đó, và nó rất đúng. Mình cho rằng, nếu nhưng người giỏi nhất mà không nhận ra mình giỏi nhất thì họ có khả năng nhìn nhận hơi kém.

Với cả cũng tuỳ định hướng nữa, nếu như là người lấy tôn chỉ đề cao sự thật như mình, thì mình rất thẳng thắn thôi, có gì nói vậy à. Mình không nghĩ rằng việc bảo code rườm rà là code rườm rà, bảo dùng dao mổ trâu giết gà với đoạn code của bạn có gì sai? Ồ, cũng có người đồng tình với mình luôn, nếu bạn cần mình có thể hỏi thêm người khác để họ đánh giá về độ tường minh trong code của bạn, tuy bạn không còn đọc topic này nhưng vẫn có thể inbox mình.

Như code của mình cũng là 1 dạng vẽ rắn thêm chân thôi. Nói chung, kiêu ngạo không phải là vấn đề, việc không biết nhìn nhận mới là vấn đề. Cảm ơn bạn đã khuyên mình thay đổi, tất nhiên là mình không thay đổi đâu.

(fizz && buzz || fizz || buzz) <$> [0..101]

Cụ thể như nào thì cứ thế triển tiếp thôi :smiley:

Bài FizzBuzz theo cá nhân mình thì bài toán có tính phân loại lập trình viên.

Một trong các nhân tố quan trọng trong khi lập trình là readability, rõ hơn nữa là understandability.
Understandability là khả năng lập trình viên có khả năng hiểu được chương trình, bao gồm: vấn đề là gì? Hướng giải quyết như thế nào? Quy trình? Các công cụ hỗ trợ (library, framework)? Đến mức chi tiết: phân loại class, phân loại hàm, câu lệnh,… Các chi tiết nhỏ đó gọi chung là factor.

Thang đo đánh giá understandability là có tổng cộng bao nhiêu factor mà lập trình viên cần phải nắm rõ khi giải quyết vấn đề. Thông thường với 1 người bình thường chỉ nhớ khoảng 7 factor trở xuống.

Ví dụ với bài toán FizzBuzz này. Có 2 cách giải quyết phổ biến nhất: thủ tục và lập trình hàm.

Thủ tục thì có 3 factor ảnh hưởng: biến đại diện cho input, biến đại diện cho output, câu lệnh if-then-else để xử lý. Phạm vi bài toán được hạn chế lại trong hàm main().

Lập trình hàm cũng có 3 factor, mỗi factor là 1 hàm có các chức năng khác nhau: hàm nhận input, hàm xử lý (xem là 1 factor hoặc là 3 factor cho 3 trường hợp con), hàm xuất output. Tổng cộng số factor là 3 hoặc 5. Đảm bảo tính understandability.

Như vậy, với bài toán FizzBuzz này, lập trình viên kinh nghiệm sẽ chọn đúng cách giải quyết cho vấn đề, là thủ tục hoặc hàm, để nếu lập trình viên khác xem lại code cũng có thể hiểu được.

Lập trình viên bình thường sẽ chọn cách để thể hiện khả năng hiểu biết của mình, dẫn đến tình trạng over-engineering. Khi đã over-engineering thì vấn đề bảo trì sau này chính lập trình viên đó gánh chịu. Ví dụ như áp dụng quá nhiều nguyên tắc SOLID của OOP, áp dụng Design Pattern vô tội vạ, áp dụng quá nhiều thư viên bên ngoài,…

1 Like

Phải nói là mặc dù chỉ là vài cmt trên một mạng xã hội ảo thôi nhưng cũng khiến mình đêm suy nghĩ đến tận lúc thiếp đi ngủ, và sáng nay cũng cứ bị vấn vương nó mãi.
Mình chợt nhận ra lỗi sai ban đầu là từ mình, khi mình lại trình bày sai quan điểm của mình khi cmt. Mục đích ban đầu là thử đưa ra 1 cách lập trình bài toán này theo 1 hướng mới, chỉ đơn giản vậy thôi, gọi là cho vui cũng được, vì dù sao mình cũng đang học lập trình hàm và cũng đang rảnh. “Lập trình theo hướng thủ tục thì quen thuộc quá rồi, thử theo hướng lập trình hàm xem sao”. Thế nên mình thử làm, và tất nhiên C# thì không phải là ngôn ngữ lập trình hàm, vì vậy nên khi làm mình phải dùng vài bước vượt qua cái ngưỡng “đơn giản”. Nhưng cuối cùng mình vẫn thể hiện được mục đích của mình khi cố làm bài này theo hướng lập trình hàm. Và sau đó mình post cho các bạn xem kết quả mình làm được. Mình tự đặt ra câu hỏi “Liệu có làm bài này theo hướng LT hàm được không ?!” và mình khoe với cái bạn cách mình làm.
Và mình nhận ra cái sai của mình là mình lại cố chứng minh cái cách làm ban đầu chỉ để cho vui của mình là một cách làm “tường minh”. Thật ra mình nghĩ nó sẽ tường minh khi mình viết trên Haskell, cơ mà trên C# thì nó lại không như vậy, và đây là điểm sai của mình khi cố chứng minh cho các bạn thấy là nó “tường minh”, theo như mình nghĩ.
Thật là xấu hổ khi mình vừa chạy trốn để không phải cmt nữa nhưng cuối cùng lại cmt trả lời bạn.

Không biết lập trình hàm là thể loại gì nhỉ ?
Là loại mới hay là loại cũ rồi đổi tên ???

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?