Oop lab/java1

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
หน้านี้เป็นส่วนหนึ่งของ oop lab

หน้านี้รวมแบบฝึกหัดการเขียนโปรแกรมภาษา Java เบื้องต้น เพื่อทบทวนการเขียนโปรแกรม นอกจากนี้จะได้ลองใช้ JUnit ด้วย

ในการทดลองเขียน (ยกเว้นข้อแรก) สามารถใส่ทุกอย่างไว้ใน project เดียวกันได้ (เช่นอาจจะใช้ชื่อว่า lab1practice) เพื่อไม่ให้ IDE เละไปด้วย project ที่หัดเขียน แต่ให้แยก class กัน โดยสั่ง new class และ new JUnit test case ประกบกันไป โดยให้ใช้ชื่อ class ตามที่ระบุในโจทย์

เกมทายเลข

  • จากในคลิป ให้แก้โปรแกรมให้โปรแกรมพิมพ์หมายเลขรอบที่ทายด้วย เช่นในรูปนี้
Round 1
10
Too low
Round 2
55
Too high

หมายเหตุ: ในภาษา Java เราสามารถ "บวก" ตัวเลขเข้ากับสตริงได้ ตัวเลขจะถูกแปลงเป็นสตริงและนำไปต่อกับสตริงเดิม ดังนั้นเราสามารถพิมพ์แบบนี้ได้

    System.out.println("Round " + 1);
  • ถ้าทายน้อยกว่า 5 ครั้ง ให้พิมพ์ตอนท้ายด้วยว่าเก่งมาก

ทดลองฟังก์ชัน abs

จากในคลิป ทดลองเขียนฟังก์ชัน abs ในคลาส MyMath และลองรัน JUnit test ด้านล่าง โดยโค้ดด้านล่างเป็นไฟล์เกือบทั้งหมด ให้ตัดไปเฉพาะส่วนที่เป็นโค้ดที่จะใช้

public class MyMath {
	
	public static int abs(int x) {
		// put your code here
	}

}
import static org.junit.Assert.*;

import org.junit.Test;

public class MyMathTest {

	@Test
	public void testAbsZero() {
		assertEquals(0, MyMath.abs(0));
	}

	@Test
	public void testAbsPositive() {
		assertEquals(100, MyMath.abs(100));
	}

	@Test
	public void testAbsNegative() {
		assertEquals(50, MyMath.abs(-50));
	}
}

ลดราคาสมาชิก

ร้านค้าแห่งหนึ่งเพิ่มระบบสมาชิกและคะแนนสะสมเพื่อกระตุ้นยอดขาย โดยมีเกณฑ์ในการลดแลกแจกแถมดังนี้

  • ไม่ใช่สมาชิก ขายราคาเต็ม
  • เป็นสมาชิก ลดราคา 10% ยกเว้นสินค้าราคามากกว่า 1000 จะลดราคา 5%
    • ถ้าสมาชิกมีแต้มสะสมเกิน 500 แต้ม จะลดเพิ่มอีก 2.5% (จากราคาที่เหลือ)

ให้เขียนเมท็อด Membership.getDiscount ที่คำนวณราคาใหม่ภายใต้วิธีการลดราคาดังกล่าว

public class Membership {
	public static double getDiscount(double price, boolean isMember, int memberPoints) {
	}
}

สำหรับชุดทดสอบด้านล่าง เนื่องจากเราทดสอบโดยการเปรียบเทียบ double เราจะต้องใส่ delta เป็น argument ที่สามด้วย (ในตัวอย่างใส่เป็น 0.001) เพื่อป้องกันปัญหา error ของการคำนวณทศนิยม

public class MembershipTest {

	@Test
	public void testNonMember() {
		assertEquals(1000, Membership.getDiscount(1000, false, 0), 0.001);
		assertEquals(400, Membership.getDiscount(400, false, 0), 0.001);
	}

	@Test
	public void testMemberWithSmallPoints() {
		assertEquals(450, Membership.getDiscount(500, true, 0), 0.001);
		assertEquals(450, Membership.getDiscount(500, true, 500), 0.001);
		assertEquals(900, Membership.getDiscount(1000, true, 100), 0.001);
		assertEquals(950.94999, Membership.getDiscount(1001, true, 100), 0.001);
		assertEquals(1900, Membership.getDiscount(2000, true, 500), 0.001);
	}

	@Test
	public void testMemberWithHighPoints() {
		assertEquals(438.75, Membership.getDiscount(500, true, 501), 0.001);
		assertEquals(877.5, Membership.getDiscount(1000, true, 600), 0.001);
		assertEquals(927.1762, Membership.getDiscount(1001, true, 600), 0.001);
		assertEquals(1852.5, Membership.getDiscount(2000, true, 501), 0.001);
	}
}

มัธยฐานของเลข 3 ตัว

เขียนเมท็อด Median3.median ที่รับจำนวนเต็มสามจำนวนแล้วคืนค่ามัธยฐานของเลขสามตัวนั้น

public class Median3 {
	public static int median(int a, int b, int c) {
		return 0;
	}
}
public class Median3Test {

	@Test
	public void testDistinctIntegers() {
		assertEquals(2, Median3.median(1, 2, 3));
		assertEquals(2, Median3.median(3, 2, 1));
		assertEquals(2, Median3.median(1, 3, 2));
		assertEquals(2, Median3.median(3, 1, 2));
	}

	@Test
	public void testWithNegativeIntegers() {
		assertEquals(2, Median3.median(-1, 2, 3));
		assertEquals(1, Median3.median(3, -2, 1));
		assertEquals(-2, Median3.median(1, -3, -2));
		assertEquals(-1, Median3.median(3, -1, -2));
	}
	
	@Test
	public void testDuplicates() {
		assertEquals(2, Median3.median(2, 2, 1));
		assertEquals(1, Median3.median(1, 3, 1));
		assertEquals(-1, Median3.median(3, -1, -1));
	}

	@Test
	public void testAllEqual() {
		assertEquals(2, Median3.median(2, 2, 2));
		assertEquals(-1, Median3.median(-1, -1, -1));
		assertEquals(0, Median3.median(0, 0, 0));
	}
}

ทดสอบจำนวนเฉพาะ

เขียนเมท็อด Prime.isPrime ในคลาส Prime ที่คืนค่า true เมื่อข้อมูลที่ป้อนมาเป็นจำนวนเฉพาะ

public class Prime {
	public static boolean isPrime(int n) {
		return false;
	}
}

สังเกตว่าเราต้องการทดสอบ boolean เพื่อความชัดเจนเราจะสั่ง assertTrue กับ assertFalse แทน

public class PrimeTest {

	@Test
	public void testPrime() {
		assertTrue(Prime.isPrime(2));
		assertTrue(Prime.isPrime(3));
		assertTrue(Prime.isPrime(5));
		assertTrue(Prime.isPrime(157));
		assertTrue(Prime.isPrime(56687));
		assertTrue(Prime.isPrime(102551));
	}

	@Test
	public void testComposite() {
		assertFalse(Prime.isPrime(4));
		assertFalse(Prime.isPrime(200));
		assertFalse(Prime.isPrime(75));
		assertFalse(Prime.isPrime(396809));
		assertFalse(Prime.isPrime(96172057));
	}

	@Test
	public void testOne() {
		assertFalse(Prime.isPrime(1));
	}
}

ค่าสูงสุด

ในข้อนี้เราจะหัดเขียนเกี่ยวกับอาร์เรย์ (array) ซึ่งจะมีหลักการเขียนทั่วไปไม่ต่างจากที่เราเคยเขียนใน C#

ให้เขียนเมท็อด ArrayMax.max ที่รับอาร์เรย์ของจำนวนเต็ม และคืนค่าจำนวนเต็มที่มากที่สุด ไม่ต้องสนใจกรณีที่อาร์เรย์เป็นอาร์เรย์ว่าง

public class ArrayMax {
	public static int max(int[] ar) {
		return ar[0];
	}
}
public class ArrayMaxTest {

	@Test
	public void testOneElement() {
		assertEquals(0, ArrayMax.max(new int[] { 0 }));
		assertEquals(100, ArrayMax.max(new int[] { 100 }));
		assertEquals(-10, ArrayMax.max(new int[] { -10 }));
	}

	@Test
	public void testWithNoDuplicate() {
		assertEquals(5, ArrayMax.max(new int[] { 1, 2, 3, 4, 5 }));
		assertEquals(5, ArrayMax.max(new int[] { 5, 4, 3 }));
		assertEquals(200, ArrayMax.max(new int[] { 100, 200, 50, 40 }));
		assertEquals(-5, ArrayMax.max(new int[] { -10, -20, -60, -5 }));
	}

	@Test
	public void testWithDuplicate() {
		assertEquals(5, ArrayMax.max(new int[] { 1, 2, 3, 5, 3, 4, 5 }));
		assertEquals(5, ArrayMax.max(new int[] { 5, 4, 3, 3, 4 }));
		assertEquals(130, ArrayMax.max(new int[] { 100, 130, 100, 50, 50, 40 }));
		assertEquals(-7, ArrayMax.max(new int[] { -10, -20, -7, -10, -60, -7 }));
	}
}

เรียงกันหรือเปล่า?

เขียนเมท็อด ArrayOrder.isAscending ที่รับอาร์เรย์แล้วคืนค่าจริงถ้าสมาชิกในอาร์เรย์มีค่าไม่ลดลง (คือจะเพิ่มขึ้นหรือเท่าเดิมก็ได้) ดูตัวอย่างจากใน TestCase

public class ArrayOrder {
	public static boolean isAscending(int[] ar) {
		return false;
	}
}
public class ArrayOrderTest {
	@Test
	public void testOneElement() {
		assertTrue(ArrayOrder.isAscending(new int[] { 1 }));
		assertTrue(ArrayOrder.isAscending(new int[] { -10 }));
		assertTrue(ArrayOrder.isAscending(new int[] { 0 }));
	}

	@Test
	public void testTwoElements() {
		assertTrue(ArrayOrder.isAscending(new int[] { 1, 2 }));
		assertTrue(ArrayOrder.isAscending(new int[] { -10, 9 }));
		assertTrue(ArrayOrder.isAscending(new int[] { 0, 1 }));
		assertFalse(ArrayOrder.isAscending(new int[] { 2, 1 }));
		assertFalse(ArrayOrder.isAscending(new int[] { -9, -10 }));
		assertFalse(ArrayOrder.isAscending(new int[] { 1, 0 }));
	}

	@Test
	public void testSimpleList() {
		assertTrue(ArrayOrder.isAscending(new int[] { 1, 2, 5, 7 }));
		assertTrue(ArrayOrder.isAscending(new int[] { -1, 10, 50 }));
		assertFalse(ArrayOrder.isAscending(new int[] { 50, 60, 70, 60 }));
		assertFalse(ArrayOrder.isAscending(new int[] { 10, 9, 8, 7, 6, 5 }));
	}

	@Test
	public void testWithDuplicates() {
		assertTrue(ArrayOrder.isAscending(new int[] { 0,0 }));
		assertTrue(ArrayOrder.isAscending(new int[] { 100, 100 }));
		assertTrue(ArrayOrder.isAscending(new int[] { 1, 1, 3 }));
		assertTrue(ArrayOrder.isAscending(new int[] { 0, 1, 1, 1 }));
		assertFalse(ArrayOrder.isAscending(new int[] { 2, 1, 3, 3 }));
		assertFalse(ArrayOrder.isAscending(new int[] { 0, 0, 1, 1, 4, 4, 2 }));
	}
}

กลับหน้าหลัง

เขียนเมท็อด ArrayReverse.reverse ที่รับอาร์เรย์ของจำนวนเต็ม และคืนอาร์เรย์ของจำนวนเต็มที่เรียงกลับหน้าหลัง

ในโค้ดที่เรามีให้ มีการสร้างอาร์เรย์ผลลัพธ์ให้แล้ว สังเกตว่าเราเรียก member length ของอาร์เรย์เพื่ออ่านความยาว

public class ArrayReverse {
  public static int[] reverse(int[] ar) {
    int[] res = new int[ar.length];

    // add your code here

    return res;
  } 
}

สังเกตการใช้เมท็อด assertArrayEquals ด้านล่างด้วย

public class ArrayReverseTest {

  @Test
  public void testEmptyArray() {
    assertArrayEquals(new int[] {}, 
        ArrayReverse.reverse(new int[] {}));    
  }
  
  @Test
  public void testOneElement() {
    assertArrayEquals(new int[] { 10 }, 
        ArrayReverse.reverse(new int[] { 10 }));    
    assertArrayEquals(new int[] { 20 }, 
        ArrayReverse.reverse(new int[] { 20 }));    
    
  }

  @Test
  public void testManyElements() {
    assertArrayEquals(new int[] { 50, 40, 30, 20, 10 }, 
        ArrayReverse.reverse(new int[] { 10, 20, 30, 40, 50 }));    
    assertArrayEquals(new int[] { 2, 1, 2, 1, 4 }, 
        ArrayReverse.reverse(new int[] { 4, 1, 2, 1, 2 }));    
    
  }
}

หา

เขียนเมท็อด ArrayFind.find ที่รับอาร์เรย์ ar และค่าที่จะค้นหา x และคืน index ของสมาชิกตัวแรกในอาร์เรย์ที่มีค่าเท่ากับ x ถ้าไม่มีให้คืน -1

public class ArrayFind {
  public static int find(int[] ar, int x) {
    return -1;
  }
}
public class ArrayFindTest {

  @Test
  public void testEmptyArray() {
    assertEquals(-1, ArrayFind.find(new int[] {}, 10));
    assertEquals(-1, ArrayFind.find(new int[] {}, 0));
  }

  @Test
  public void testNotFound() {
    assertEquals(-1, ArrayFind.find(new int[] { 1, 2, 3 }, 10));
    assertEquals(-1, ArrayFind.find(new int[] { -1, 1, 100 }, 0));
  }

  @Test
  public void testFindUnique() {
    assertEquals(0, ArrayFind.find(new int[] { 1, 2, 3 }, 1));
    assertEquals(1, ArrayFind.find(new int[] { -1, 1, 10, 100 }, 1));
    assertEquals(3, ArrayFind.find(new int[] { -1, 1, 10, 100 }, 100));
  }

  @Test
  public void testFindFirst() {
    assertEquals(0, ArrayFind.find(new int[] { 1, 2, 3, 1 }, 1));
    assertEquals(1, ArrayFind.find(new int[] { -1, 1, 10, 1, 100 }, 1));
    assertEquals(3, ArrayFind.find(new int[] { -1, 1, 10, 100, 100 }, 100));
  }
}

นับมากกว่า

เขียนเมท็อด ArrayCountCond.countGreaterThan ที่รับอาร์เรย์ ar และจำนวนเต็ม x แล้วคืนจำนวนสมาชิกในอาร์เรย์ที่มีค่ามากกว่า x

public class ArrayCountCond {
  public static int countGreaterThan(int[] ar, int x) {
    return 0;
  }
}
public class ArrayCountCondTest {

  @Test
  public void testEmptyArray() {
    assertEquals(0, ArrayCountCond.countGreaterThan(new int[] {}, 100));
  }

  @Test
  public void testNoGreaterThan() {
    assertEquals(0, 
        ArrayCountCond.countGreaterThan(new int[] { 200, 300 }, 400));
    assertEquals(0, 
        ArrayCountCond.countGreaterThan(new int[] { 100, 200 }, 300));
  }

  @Test
  public void testSomeGreaterThan() {
    assertEquals(1, 
        ArrayCountCond.countGreaterThan(new int[] { 301, 200, 300 }, 300));
    assertEquals(2, 
        ArrayCountCond.countGreaterThan(new int[] { 99, 100, 200, 5, 300 }, 100));
  }
}

นับคู่เรียงผิด

เขียนเมท็อด Inversion.count ที่รับอาร์เรย์ ar จากนั้นนับจำนวน inversion ใน ar โดยที่ inversion คือคู่ของข้อมูลที่เรียงผิดลำดับกัน ถ้าเราต้องการให้อาร์เรย์เรียงจากน้อยไปหามาก

เช่น ในอาร์เรย์: 1, 4, 3, 2, 5 จะมี inversion คือ (4,3), (4,2), (3,2) ดังนั้นถ้าเรานับคู่ที่เรียงผิด จะได้ว่ามี 3 คู่

public class Inversion {
  public static int count(int[] ar) {
    return 0;
  }
}
public class InversionTest {

  @Test
  public void testEmptyArray() {
    assertEquals(0, Inversion.count(new int[] {}));
  }

  @Test
  public void testOneElement() {
    assertEquals(0, Inversion.count(new int[] { 7 }));
  }

  @Test
  public void testTwoElements() {
    assertEquals(0, Inversion.count(new int[] { 1, 7 }));
    assertEquals(1, Inversion.count(new int[] { 7, 3 }));
  }

  @Test
  public void testSorted() {
    assertEquals(0, Inversion.count(new int[] { 1, 2, 3, 4, 5, 6 }));
    assertEquals(6, Inversion.count(new int[] { 6, 5, 4, 3 }));
  }

  @Test
  public void testList() {
    assertEquals(2, Inversion.count(new int[] { 1, 3, 2, 5, 4 }));
    assertEquals(4, Inversion.count(new int[] { 6, 5, 10, 3 }));
  }
}