Coding Bat: Python. Logic-1

All solutions were successfully tested on 17 April 2013.

cigar_party:

def cigar_party(cigars, is_weekend):
  if is_weekend:
    return cigars >= 40
  return 40 <= cigars <= 60

Pay attention to the last line! In Python it is possible to concatenate comparisons, just like you would do it in mathematics. This can lead to much cleaner code. In my opinion, the solution from the website is worse, but not just for that reason alone:

def cigar_party(cigars, is_weekend):
  if is_weekend:
    return (cigars >= 40)
  else:
    return (cigars >= 40 and cigars <= 60)

date_fashion:

def date_fashion(you, date):
  if you <= 2 or date <= 2:
    return 0
  if you >= 8 or date >= 8:
    return 2
  return 1

squirrel_play:

def squirrel_play(temp, is_summer):
  if is_summer:
    return 60 <= temp <= 100
  return 60 <= temp <= 90

caught_speeding:

def caught_speeding(speed, is_birthday):
  if is_birthday:
    speed -= 5
    
  if speed <= 60:
      return 0
  if 60 < speed <= 80:
    return 1
  return 2

sorta_sum:

def sorta_sum(a, b):
  if 10 <= a + b < 20:
    return 20
  return a + b

It is not necessary to put “a + b” in line 2 inside parentheses due to the rules of precedence of operators. A less experienced human reader might be able to parse this line more quickly with parens, though. However, you shouldn’t assume that you write code for a complete beginner.

alarm_clock:

def alarm_clock(day, vacation):
  if not vacation:
    if 1 <= day <= 5:
      return '7:00'
    return '10:00'
 
  if 1 <= day <= 5:
    return '10:00' 
  return 'off'

love6:

def love6(a, b):
  return a == 6 or b == 6 or (a + b) == 6 or abs(a - b) == 6

What, this looks ugly you say? I completely agree, and there is a much more pleasant solution:

def love6(a, b):
  return 6 in [a, b, a + b, abs(a - b)]

in1to10:

def in1to10(n, outside_mode):
  if not outside_mode:
    return n in range(1, 11)
  return n <= 1 or n >= 10

near_ten:

def near_ten(num):
 # return 0 <= (num % 10) <= 2 or 8 <= (num % 10) <= 10
 return num % 10 in [0,1,2,8,9,10]

Again, do you go for ugly or nice and clean?

Coding Bat: Python. List-1

All solutions were successfully tested on 16 April 2013.

first_last6:

def first_last6(nums):
  return nums[0] == 6 or nums[-1] == 6

same_first_last:

def same_first_last(nums):
  return len(nums) >= 1 and nums[0] == nums[-1]

make_pi:

def make_pi():
  return [3, 1, 4]

common_end:

def common_end(a, b):
  return a[0] == b[0] or a[-1] == b[-1]

sum3:

def sum3(nums):
  #return nums[0] + nums[1] + nums[2]
  return sum(nums)

Either way works. The version I’ve commented out is less elegant, though.

rotate_left3:

def rotate_left3(nums):
  return [nums[1], nums[2], nums[0]] 

reverse3:

def reverse3(nums):
  #return [nums[2], nums[1], nums[0]]
  return nums[::-1]

Again, the second version is more elegant or, as some phrase it, more “pythonic”.

max_end3:

def max_end3(nums):
  m = max(nums[0], nums[2])
  return [m, m, m]

For matters of comparison, here is the solution from the website:

def max_end3(nums):
  big = max(nums[0], nums[2])
  nums[0] = big
  nums[1] = big
  nums[2] = big
  return nums

It is less expressive and, frankly, a bit painful to look at. A much nicer way to assign “big” to three variables at once would be one of the two following ways:

def max_end3(nums):
  big = max(nums[0], nums[2])
  #nums[0], nums[1], nums[2] = big, big, big
  nums[0], nums[1], nums[2] = (big, ) * 3
  return nums

sum2:

def sum2(nums):
  if len(nums) == 0:
    return 0
  if len(nums) == 1:
    return nums[0]
  return nums[0] + nums[1]

middle_way:

def middle_way(a, b):
  return [a[1], b[1]]

make_ends:

def make_ends(nums):
  return [nums[0], nums[-1]]

has23:

def has23(nums):
  return 2 in nums or 3 in nums

Do you remember what this looked like in Java?

Coding Bat: Python. String-1

All solutions were successfully tested on 15 April 2013.

hello_name:

def hello_name(name):
  return "Hello " + name + "!"

make_abba:

def make_abba(a, b):
  return a + b + b + a

make_tags:

def make_tags(tag, word):
  return "<" + tag + ">" + word + "</" + tag + ">"

make_out_word:

def make_out_word(out, word):
  return out[:2] + word + out[2:]

extra_end:

def extra_end(str):
  return str[-2:] * 3

The asterisk is overloaded in Python, as you see in this example. An alternative solution would be to concatenate with “+”, as you’ve seen it before.

first_two:

def first_two(str):
  if len(str) <= 2:
    return str
  return str[:2]

first_half:

def first_half(str):
  return str[:len(str)/2]

without_end:

def without_end(str):
  return str[1:-1]

combo_string:

def combo_string(a, b):
  if len(a) > len(b):
    return b + a + b
  return a + b + a

non_start:

def non_start(a, b):
  return a[1:] + b[1:]

left2:

def left2(str):
  return str[2:] + str[:2]

Coding Bat: Python. Warmup-2

All solutions were successfully tested on 13 April 2013.

string_times:

def string_times(str, n):
  return str * n

front_times:

def front_times(str, n):
  if len(str) < 3:
    return str * n
  return str[:3] * n

string_bits:

def string_bits(str):
  result = ''
  for n in range(0, len(str)):
    if n%2 == 0:
      result += str[n]
  return result

string_splosion:

def string_splosion(str):
  result = ''
  for n in range(0,len(str)+1):
    result += str[:n]
  return result

last2:

def last2(str):    
  count = 0
  for i in range(len(str)-2):
    if str[i:i+2] == str[-2:]:
      count += 1   
  return count

Below I show the solution from the website, which is overambitous since there is no need to specifically process cases in which the input string is too short. The reason is that the for loop takes the length of the string into account. If the range was given as an absolute number, say, range(10), then a separate check that the string is long enough would have been necessary.

def last2(str):
  # Screen out too-short string case.
  if len(str) < 2:
    return 0
  
  # last 2 chars, can be written as str[-2:]
  last2 = str[len(str)-2:]
  count = 0
  
  # Check each substring length 2 starting at i
  for i in range(len(str)-2):
    sub = str[i:i+2]
    if sub == last2:
      count = count + 1

  return count

array_count9:

def array_count9(nums):
  count = 0
  for element in nums:
    if element == 9:
      count += 1
  return count

Please note that Python allows you to conveniently name variables, which makes the resulting code a lot more readable. In Java you would probably stick to variable names like “i” due to the fact that you have to repeat them so often. Below is a solution in Java to illustrate this issue. Imagine you would have written “element” instead of “i”:

public int arrayCount9(int[] nums) {
	int result = 0;
	for (int i = 0; i < nums.length; i++) {
		if (nums[i] == 9)
			result++;
	}
	return result;
}

array_front9:

def array_front9(nums):
  for element in nums[:4]:
    if element == 9:
      return True
  return False

Again, there is a slight inconvenience in the solution given on Coding Bat:

def array_front9(nums):
  # First figure the end for the loop
  end = len(nums)
  if end > 4:
    end = 4
  
  for i in range(end):  # loop over index [0, 1, 2, 3]
    if nums[i] == 9:
      return True
  return False

It is superfluous to consider the length of the array since the slice [:4] will be processed at most up to but not including position 4. If the array is shorter, the procedure will simply stop. I have seen pythonistas defend similar code by referring to the Zen of Python, particularly the line “Explicit is better than implicit.” However, I consider this to be a bizarre interpretation. If you write code like that you only show that you have not yet “grokked” Python and instead translate from another language. You can write Java in Python, but not the other way round, so if you’ve got the option to write more elegant code, why wouldn’t you want to make use of that opportunity?

array123:

def array123(nums):
  for i in range(len(nums)-2):
    if nums[i] == 1 and nums[i+1] == 2 and nums[i+2] == 3:
      return True
  return False

But, wait, this can be done more nicely:

def array123(nums):
  for i in range(len(nums)-2):
    if nums[i:i+3] == [1,2,3]:
      return True
  return False

string_match:

def string_match(a, b):
  min_length = min(len(a), len(b))
  
  count = 0  
  for i in range(min_length-1):
    if a[i:i+2] == b[i:i+2]:
      count += 1
  return count

Coding Bat: Python. Warmup-1

All solutions were successfully tested on 13 April 2013.

sleep_in:

def sleep_in(weekday, vacation):
  return not weekday or vacation

As you can already see, it’s pleasant to write Python code, and this language is very readable, too. Just compare this method with the equivalent in Java:

public boolean sleepIn(boolean weekday, boolean vacation) {
  return (! weekday || vacation);
}

monkey_trouble:

def monkey_trouble(a_smile, b_smile):
  return a_smile and b_smile or not a_smile and not b_smile

sum_double:

def sum_double(a, b):
  if a == b:
    return a * 4
  return a + b

diff21:

def diff21(n):
  if n > 21:
    return abs(n-21) * 2
  return abs(n-21)

parrot_trouble:

def parrot_trouble(talking, hour):
  return talking and (hour < 7 or hour > 20)

makes10:

def makes10(a, b):
  return a + b == 10 or a == 10 or b == 10

near_hundred:

def near_hundred(n):
  return abs(n-100) <= 10 or abs(n-200) <= 10

pos_neg:

def pos_neg(a, b, negative):
  if negative:
    return a < 0 and b < 0
  return a * b < 0

I took a shortcut in the last line since the result will be negative if one of the numbers is negative, and the other positive. The sample solution on the website is more verbose:

def pos_neg(a, b, negative):
  if negative:
    return (a < 0 and b < 0)
  else:
    return ((a < 0 and b > 0) or (a > 0 and b < 0))

not_string:

def not_string(str):
  if str[:3] == "not":
    return str
  return "not " + str

missing_char:

def missing_char(str, n):
  return str[:n] + str[n+1:]

front_back:

def front_back(str):
  if len(str) == 0 or len(str) == 1:
    return str
  return str[-1] + str[1:-1] + str[0]

front3:

def front3(str):
  if len(str) < 3:
    return str * 3
  return str[:3] * 3