Post

程序基础练习1

codewar和leetcode

编程练习网站codewars是一个练习编程题目的网站,对于编程练习网站,我们已经很熟悉了leetcode,不过leetcode是非常侧重算法的,而codewars是侧重程序应用本身的,对于了解程序的本身而言,codewars是更加适合的,等熟练掌握以后,进阶可以去练习leetcode,在很长一段时间,我都将以熟练使用程序本身为目的,所以从基础打起

1. 创造数组

1
2
3
4
5
6
7
8
9
10
11
// Add the value "codewars" to the array websites 1,000 times.

public class KataExampleTwist
{
    public static String[] kataExampleTwist()
    {
        String[] websites = {};
        return websites;
    }
}

这是最简单的一道题,给websites数组添加1000个字符串codewars

1
2
3
4
5
6
7
8
9
10
11
12
13
// Add the value "codewars" to the array websites 1,000 times.

import java.util.*;
public class KataExampleTwist
{
    public static String[] kataExampleTwist()
    {
        String[] websites = new String[1000];
	Arrays.fill(websites,"codewars");
        return websites;
    }
}

实现的方式很多,可以通过Arrays.fill方法添加,也可以直接循环赋值

1
2
3
4
5
6
7
8
9
10
11
public class KataExampleTwist
{
    public static String[] kataExampleTwist()
    {
        String[] websites = new String[1000];
	for(int i = 0; i < 1000; i++) 
	  websites[i] = "codewars";
        return websites;
    }
}

当然,还有很多其他方式,这都是考察基础的东西

动态语言

在直接应用上,动态语言还是要方便不少,还是用我熟悉的ruby来比较一下

1
websites = ["codewars"] * 1000

没错,不需要考虑数据类型,不需要考虑内存空间,不需要循环一个一个复制,数组甚至可以直接用乘法,它甚至知道乘法是把里面的元素弄成多个拷贝,用更加面向对象一点的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
websites = []

#1
1000.times{ websites << "codewars"}
#2
1000.times{ websites += ["codewars"]}
#3
1000.times{ websites.push("codewars")}
#4
websites = Array.new(1000, "codewars")
#5
websites = Array.new(1000){|_| "codewars"} 
#6
websites = (1..1000).map{|_| "codewars"}
#7
websites = ("codewars " * 1000).split

可以看出,动态语言实现基本的数据逻辑是非常简单的,我这里随便写了7种ruby的实现方式1-3是以数字1000为对象实现的,4-5是以数组对象实现,6是以Range对象实现,7是以字符串对象实现

对比

因为Java是在学习中,所以以后也会拿几种语言来对比加深印象和理解,不同的语言大部分是相同的,少部分本身特点,结合起来学习会更加好理解

2. 字符串替换

题目是将一个字符串的小写aeiou去掉,返回如下结果

1
2
3
4
"hello"     -->  "hll"
"codewars"  -->  "cdwrs"
"goodbye"   -->  "gdby"
"HELLO"     -->  "HELLO"

最直接最机械的方式

1
2
3
4
5
6
7
8
9
10
public class Kata {
  public static String shortcut(String input) {
    return input.replace("a","")
      .replace("e","")
      .replace("i","")
      .replace("o","")
      .replace("u","");   
  }
}

当然更直接更优雅的

1
2
3
4
5
public class Kata {
  public static String shortcut(String input) {
    return input.replaceAll("[aeiou]", "");
  }
}

熟悉的ruby方式

1
2
3
4
5
6
def shortcut(s)
#1
  s.gsub(/[aeiou]/,"")
#2
  s.tr("aeiou","")
end

3. 16进制转换10进制

题目:给定一个16进制的字符串,返回10进制的结果

1
2
3
4
5
6
7
public class Kata {

  public static int hexToDec(final String hexString) {
    return Integer.parseInt(hexString, 16);
  }
}

1
2
3
def hex_to_dec(hex)
  hex.to_i(16)
end

如果不熟悉的话,对于java,需要从APIjava.lang.Integer类中找到类静态方法,而ruby是字符串的String类的实例方法to_i,从这几个例子来看,java虽然也是OO派的语言,但实际上使用还是有点函数式的思维,但是ruby就不一样了,感觉OO的形式最极致,写多了ruby在换别的多少还是有点不适应

4. 类和实例

题目简介:返回一个数组,数组第一个是Man类型,第二个是Woman类型,男人和女人都属于Human的子类

1
2
3
4
5
6
7
8
9
10
11
12
public class God {
  public static Human[] create(){
    return new Human[]{new Man(), new Woman()};
  }
}
class Human{
}
class Man extends Human{
}
class Woman extends Human{
}

这里是属于class和继承最基本的概念,而且因为这里必须是在同一个文件中定义外部类,还涉及到一个文件中只有一个public的知识点。所以定义的时候不加权限修饰符,当然这里还可以用abstractinterface来定义,这里就不用了

1
2
3
4
5
6
7
8
9
10
class Human
end
class Man < Human
end
class Woman < Human
end

def god
  [Man.new, Woman.new]
end

当然从直接的语言感官来讲,还是ruby更直观好理解一点

5.字符串计算操作符

题目描述:给一个函数3个参数(final double x, final String op, final double y),例如(6,”-“, 1.5),返回6 - 1.5,也就是4.5,其中计算符op不是”+-*/”则返回null,除法除以0也返回null

1
2
3
4
5
6
7
8
9
10
11
public class Calculator {
  public static Double calculate(final double x, final String op, final double y) {
    switch (op) {
      case "+": return x + y;
      case "-": return x - y;
      case "*": return x * y + 0.0;
      case "/": return y == 0 ? null : x / y;
    }
    return null;
  }
}

这里有个有意思的地方就是对于”*“,为什么后面要加个0.0多此一举?这就是练习基础的重要性,如果不加这个0.0,则这道题的测试就会通不过,因为比如-1.0 * 0.0 = -0.0,一般认为0是以正号形式存在,而-0.0 + 0.0 = 0.0所以需要加个看起来没有意义的0.0了,这就是一个非常不明显的大坑。

1
2
3
4
5
6
7
8
9
10
11
12
13
def calculate(x, op, y)
  case op
    when "+"
      return x + y
    when "-"
      return x - y
    when "*"
      return x * y
    when "/"
      return y == 0 ? "null" : x / y
  end
  return "null"
end

对于动态语言,乘法则没有-0.0这种说法

6. 阶乘

题目描述:给定参数n,返回n的阶乘,要求n不小于0且n不大于12,否则抛,否则抛IllegalArgumentException异常,经典题目,可以用递归,也可以用迭代

1
2
3
4
5
6
public class Factorial {
  public int factorial(int n) {
    if(n < 0 || n > 12) throw new IllegalArgumentException("Illega params");
    return n <= 1 ? 1 : n * factorial(n - 1);
  }
}

这里用递归方法

7.首字母大写

题目描述:给一个字符串,返回首字母大写,其他字母小写

1
2
3
4
5
public class GreetMe{
  public static String str_capital(String name){
    return "Hello " + name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
  }
}

这里主要需要使用substringtoUppercasetoLowerCase实例方法

1
2
3
def str_capital(name)
  name.capitalize
end

动态语言直接封装了很多实例方法,如果对方法熟练度高的话非常方便

8. 矩阵相加

题目描述: 给定两个n*n的二维数组,要求返回每个位置相加的二位数组,例如 [[1,2],[3,4]],[[1,2],[3,4]],返回[[2,4],[6,8]]

1
2
3
4
5
6
7
8
9
10
11
public class Kata {
  public static int[][] matrixAddition(int[][] a, int[][] b) {
 
    for(int i=0; i<a.length; i++){
      for(int j=0; j<a.length; j++){
        a[i][j]+=b[i][j];
      }
    }
    return a;
  }
}

java是直接自己用基本数据类型和循环实现

1
2
3
def matrixAddition(a, b)
  a.zip(b).map { |el| el.transpose.map(&:sum) }
end

是的,动态语言就是这么简洁,但是简洁的代价是不好维护,里面用到了zip,map,transpose,&:,block等非常多的知识点,其实里面的东西挺多的,以后再说了

9. 创建类

问题描述:给一个整数数组[width, length, height],要求创建block类实现返回长宽高,面积,体积的方法,这个是属于最最基础的概念,但是我手写还是没做到一把过,还是会出错,所以还是值得记录理解下,而且每种语言的类的实现方式不一样,细节概念也不一样,可以做对比理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Block{
  private int width;
  private int length;
  private int height;
  public Block(int[] arr){
    width = arr[0];
    length = arr[1];
    height = arr[2];
  }
  public int getWidth(){
    return width;
  }
  public int getLength(){
    return length;
  }
  public int getHeight(){
    return height;
  }
  public int getVolume(){
    return width * length * height;
  }
  public int getSurfaceArea(){
    return 2* (width * length + width * height + length * height);
  }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Block
  def initialize(args)
    @width, @length, @height = args
  end
  
  def get_width
    @width
  end
  
  def get_length
    @length
  end
  
  def get_height
    @height
  end
  
  def get_volume
    @width * @length * @height
  end
  
  def get_surface_area
    2 * (@width * @length + @width * @height + @length * @height)
  end
end

可以看到,两个语言构造函数形式不一样,实例变量形式不一样,当然类变量和类方法这里没体现,getter,setter方法也是有区别的,这里也暂时没体现

TO BE CONTINUE

This post is licensed under CC BY 4.0 by the author.