紧凑显示java,如何将“紧凑” Python移植为“紧凑” Java?

这篇博客讨论了一位学习者如何将一个用Python编写的递归函数,用于计算给定硬币面额列表下找零的方案数,转换为Java代码。虽然Java版本的代码变得更冗长,但作者指出这反映了两种语言的设计哲学差异。在Python中,列表操作更为简洁,而在Java中,考虑到性能和清晰度,代码通常需要更多步骤。博客还提出了解决方案,以更接近Python的简洁性来编写Java代码。
摘要由CSDN通过智能技术生成

一位朋友正在在线进行Scala课程并分享了此课程。

# Write a recursive function that counts how many different ways you can make

# change for an amount, given a list of coin denominations. For example, there

# are 3 ways to give change for 4 if you have coins with denomiation 1 and 2:

# 1+1+1+1, 1+1+2, 2+2.

如果您正在参加并且仍在研究解决方案,请不要阅读此内容!

(免责声明:即使我的Python解决方案可能是错误的,我也不想影响您的思维方式(如果您在学习过程中,一种或另一种方式!)我认为,其中的思维方式会产生学习效果,而不仅仅是“解决” ...)

那边...

我以为我可以在Python中使用它,因为我没有它的Scala排行榜(我自己不在这门课程上,只是对学习Python和Java感兴趣,欢迎“练习”进行练习)。

这是我的解决方案,我想使用尽可能紧凑的表示法移植到Java:

def show_change(money, coins, total, combo):

if total == money:

print combo, '=', money

return 1

if total > money or len(coins) == 0:

return 0

c = coins[0]

return (show_change(money, coins, total + c, combo + [c]) +

show_change(money, coins[1:], total, combo))

def make_change(money, coins):

if money == 0 or len(coins) == 0:

return 0

return show_change(money, list(set(coins)), 0, [])

def main():

print make_change(4, [2, 1])

if __name__ == '__main__':

main()

问题

我可以在Java中做得这么紧凑,允许使用JDK外部的库吗?

我尝试自己进行移植,但是它变得非常冗长,我认为通常的“一定有更好的方法”!

这是我的尝试:

import java.util.ArrayList;

import java.util.List;

import com.google.common.collect.Lists;

import com.google.common.primitives.Ints;

public class MakeChange {

static int makeChange(int money, int[] coins) {

if (money == 0 || coins.length == 0) {

return 0;

}

return showChange(money, Ints.asList(coins), 0, new ArrayList());

}

static int showChange(int money, List coins, int total,

List combo) {

if (total == money) {

System.out.printf("%s = %d%n", combo, total);

return 1;

}

if (total > money || coins.isEmpty()) {

return 0;

}

int c = coins.get(0);

List comboWithC = Lists.newArrayList(combo);

comboWithC.add(c);

return (showChange(money, coins, total + c, comboWithC) + showChange(money,

coins.subList(1, coins.size()), total, combo));

}

public static void main(String[] args) {

System.out.println(makeChange(4, new int[] { 1, 2 }));

}

}

具体来说,我不喜欢的是要做下面的事情,只是传递列表的副本并附加一个元素:

List comboWithC = Lists.newArrayList(combo);

comboWithC.add(c);

请告诉我Java的紧凑性和可读性。我还是这两种语言的初学者。

解决方案

确实,您在这里所做的几乎所有操作都可以直接转换为Java,而无需太多冗长的内容。

例如:

def make_change(money, coins):

if money == 0 or len(coins) == 0: return 0

return calculate_change(money, list(set(coins)), 0)

Java的明显等效项是:

public static int make_change(int money, int coins[]) {

if (money == 0 || coins.length == 0) return 0;

return calculate_change(money, coins, 0);

}

在这里和那里多了几句话,由于右括号而增加了一行,当然还有显式类型……但是除此之外,没有什么大的变化。

当然,更多的Python和Javariffic版本(等效词是什么?)将是:

def make_change(money, coins):

if money == 0 or len(coins) == 0:

return 0

return calculate_change(money, list(set(coins)), 0)

Java的明显等效项是:

public static int make_change(int money, int coins[]) {

if (money == 0 || coins.length == 0) {

return 0;

}

return calculate_change(money, coins, 0);

}

因此,Java获得了一个额外的结尾括号加上一些空格。仍然没什么大不了的。

将整个内容main放到一个类中,然后变成一个方法,大约增加了3行。初始化一个显式数组变量而不是[2, 1]用作文字常量还要多1个。而System.out.println长于几个字符print,而length长于3个字符len,每个评论需要两个字符//,而不是一个#。但我怀疑这是您所担心的。

最终,总共只有一条线很棘手:

return (calculate_change(money, coins, total + c, combo + [c]) +

calculate_change(money, coins[1:], total, combo))

A Java int coins[] doesn't have any way to say "give me a new array with the tail of the current one". The easiest solution is to pass an extra start parameter, so:

public static int calculate_change(int money, int coins[], int start, int total) {

if (total == money) {

return 1;

}

if (total > money || coins.length == start) {

return 0;

}

return calculate_change(money, coins, 0, total + coins[start]) +

calculate_change(money, coins, start + 1 total);

}

In fact, nearly everything can be trivially converted to C; you just need to pass yet another param for the length of the array, because you can't calculate it at runtime as in Java or Python.

The one line you're complaining about is an interesting point that's worth putting a bit more thought into. In Python, you've got (in effect):

comboWithC = combo + [c]

With Java's List, this is:

List comboWithC = Lists.newArrayList(combo);

comboWithC.add(c);

This is more verbose. But that's intentional. Java List<> is not meant to be used this way. For small lists, copying everything around is no big deal, but for big lists, it can be a huge performance penalty. Python's list was designed around the assumption that most of the time, you're dealing with small lists, and copying them around is perfectly fine, so it should be trivial to write. Java's List was designed around the assumption that sometimes, you're dealing with huge lists, and copying them around is a very bad idea, so your code should make it clear that you really want to do that.

The ideal solution would be to either use an algorithm that didn't need to copy lists around, or to find a data structure that was designed to be copied that way. For example, in Lisp or Haskell, the default list type is perfect for this kind of algorithm, and there are about 69105 recipes for "Lisp-style lists in Java" or "Java cons" that you should be able to find online. (Of course you could also just write your a trivial wrapper around List that added an "addToCopy" method like Python's __add__, but that's probably not the right answer; you want to write idiomatic Java, or why use Java instead of one of the many other JVM languages?)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值