Fork me on GitHub

Codewar_Practice

在codewar上练习的记录,包含题目/我的解/最佳解。

In [ ]:
print('hello,python3')

1. Replace With Alphabet Position

In this kata you are required to, given a string, replace every letter with its position in the alphabet.

If anything in the text isn't a letter, ignore it and don't return it.

a being 1, b being 2, etc.

As an example:

alphabet_position("The sunset sets at twelve o' clock.")
Should return "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11" as a string.

In [32]:
# 我的代码my code
def alphabet_position(text):
    dict1 = {chr(x + 96):x for x in range(1,27)}
    dict2 = {chr(x + 64):x for x in range(1,27)}
    Letter =dict(dict1, **dict2)
    result = ''
    for tx in text:
        if tx in Letter:
            if result:
                result = result + ' ' + str(Letter[tx])
            else:
                              
    return result


alphabet_position('mom is good')
Out[32]:
'13 15 13 9 19 7 15 15 4'
In [33]:
# 别人的代码 others
def alphabet_position(text):
    return ' '.join(str(ord(c) - 96) for c in text.lower() if c.isalpha())

alphabet_position('mom is good')
Out[33]:
'13 15 13 9 19 7 15 15 4'

2. Sum of two lowest positive integers

Create a function that returns the sum of the two lowest positive numbers given an array of minimum 4 integers. No floats or empty arrays will be passed.

For example, when an array is passed like [19, 5, 42, 2, 77], the output should be 7.

[10, 343445353, 3453445, 3453545353453] should return 3453455.

Hint: Do not modify the original array.

In [3]:
# 我的代码O(NlogN)
def sum_two_smallest_numbers(numbers):
    temp = sorted(numbers)
    return temp[0] + temp[1]

sum_two_smallest_numbers(numbers)
Out[3]:
7
In [ ]:
# 别人的代码  O(NlogN)
def sum_two_smallest_numbers(numbers):
    return sum(sorted(numbers)[:2])


# O(N)
def sum_two_smallest_numbers(numbers):
    smallest1 = None
    smallest2 = None 
    for n in numbers: 
        if not smallest1 or n < smallest1: 
            smallest2 = smallest1
            smallest1 = n 
        elif not smallest2 or n < smallest2: 
            smallest2 = n 
    return smallest1 + smallest2

3. Format a string of names like 'Bart, Lisa & Maggie'

Given: an array containing hashes of names

Return: a string formatted as a list of names separated by commas except for the last two names, which should be separated by an ampersand.

Example:

namelist([ {'name': 'Bart'}, {'name': 'Lisa'}, {'name': 'Maggie'} ])
# returns 'Bart, Lisa & Maggie'
namelist([ {'name': 'Bart'}, {'name': 'Lisa'} ])
# returns 'Bart & Lisa'
namelist([ {'name': 'Bart'} ])
# returns 'Bart'
namelist([])
# returns ''
In [27]:
# 我的实现
def namelist(names):
    length = len(names)
    if length == 0:
        return ''
    elif length == 1:
        return names[0]['name']
    else:
        return ', '.join(name['name'] for name in names[:-1]) + ' & ' + names[-1]['name']
    

namelist([ {'name': 'Bart'}, {'name': 'Lisa'} ])
Out[27]:
'Bart & Lisa'
In [30]:
# 别人的实现
def namelist(names):
    if len(names) > 1:
        return '{} & {}'.format(', '.join(name['name'] for name in names[:-1]), 
                                names[-1]['name'])
    elif names:
        return names[0]['name']
    else:
        return ''

4. Isograms

An isogram is a word that has no repeating letters, consecutive or non-consecutive. Implement a function that determines whether a string that contains only letters is an isogram. Assume the empty string is an isogram. Ignore letter case.

is_isogram("Dermatoglyphics" ) == true  
is_isogram("aba" ) == false
is_isogram("moOse" ) == false # -- ignore letter case
In [19]:
# 我的代码
def is_isogram(string):
    # True表示没有出现过,False表示字符已经出现过至少一次
    Letters = {chr(x + 96):True for x in range(1,27)}
    for c in string.lower():
        if c in Letters and Letters[c]:
            Letters[c] = False
        else:
            return False 
    return True

is_isogram("moOse" )
Out[19]:
False
In [21]:
# 别人的代码
# 这个只能检测重复字符,没有考虑到字母外的其他字符。
def is_isogram(string):
    return len(string) == len(set(string.lower()))


def is_isogram(string):
    string = string.lower()
    for letter in string:
        if string.count(letter) > 1: return False
    return True

5. Reversed Words

Complete the solution so that it reverses all of the words within the string passed in.

Example:

reverseWords("The greatest victory is that which requires no battle")
// should return "battle no requires which that is victory greatest The"

In [22]:
# 我的代码
def reverseWords(str):
    return ' '.join(reversed(str.split()))

reverseWords("The greatest victory is that which requires no battle")
Out[22]:
'battle no requires which that is victory greatest The'
In [ ]:
# 别人的代码
def reverseWords(str):
    return " ".join(str.split(" ")[::-1])

6. Title Case

A string is considered to be in title case if each word in the string is either (a) capitalised (that is, only the first letter of the word is in upper case) or (b) considered to be an exception and put entirely into lower case unless it is the first word, which is always capitalised.

Write a function that will convert a string into title case, given an optional list of exceptions (minor words). The list of minor words will be given as a string with each word separated by a space. Your function should ignore the case of the minor words string -- it should behave in the same way even if the case of the minor word string is changed.

Arguments (Haskell)

First argument: space-delimited list of minor words that must always be lowercase except for the first word in the string. Second argument: the original string to be converted.

Arguments (Other languages)

First argument (required): the original string to be converted. Second argument (optional): space-delimited list of minor words that must always be lowercase except for the first word in the string. The JavaScript/CoffeeScript tests will pass undefined when this argument is unused.

Example

title_case('a clash of KINGS', 'a an the of') # should return: 'A Clash of Kings'
title_case('THE WIND IN THE WILLOWS', 'The In') # should return: 'The Wind in the Willows'
title_case('the quick brown fox') # should return: 'The Quick Brown Fox'
In [14]:
# 我的代码
def title_case(title, minor_words = ''):
    if minor_words:
        title = title_case(title).split()
        for index, c in enumerate(title[1:]):
            for word in minor_words.split():
                if word.lower() == c.lower(): title[index+1] = word.lower()
        return ' '.join(title)      
    else:
        return ' '.join(c[0].upper()+c[1:] for c in title.lower().split())
         
title_case('a clash of KINGS', 'a an the of')
Out[14]:
'A Clash of Kings'
In [13]:
# Others code 666
def title_case(title, minor_words=''):
    title = title.capitalize().split()
    minor_words = minor_words.lower().split()
    return ' '.join([word if word in minor_words else word.capitalize() for word in title])

title_case('aB clash of KINGS', 'ab an the of')
Out[13]:
'Ab Clash of Kings'

7. Create Phone Number

Write a function that accepts an array of 10 integers (between 0 and 9), that returns a string of those numbers in the form of a phone number.

Example:
create_phone_number([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) # => returns "(123) 456-7890"
The returned format must be correct in order to complete this challenge. Don't forget the space after the closing parentheses!

In [4]:
# 我的代码
def create_phone_number(n):
    if len(n) < 10:
        return None
    else:
        n = [str(c) for c in n]
        return '({}) {}-{}'.format(''.join(n[:3]), ''.join(n[3:6]), ''.join(n[6:10]))
    
create_phone_number([1, 2, 3, 4, 5, 6, 7, 8, 9, 0,9]) 
Out[4]:
'(123) 456-7890'
In [7]:
# 别人的代码
def create_phone_number(n):
    return "({}{}{}) {}{}{}-{}{}{}{}".format(*n)

def create_phone_number(n):
    n = ''.join(map(str,n))
    return '(%s) %s-%s'%(n[:3], n[3:6], n[6:])

8.WeIrD StRiNg CaSe

Write a function toWeirdCase (weirdcase in Ruby) that accepts a string, and returns the same string with all even indexed characters in each word upper cased, and all odd indexed characters in each word lower cased. The indexing just explained is zero based, so the zero-ith index is even, therefore that character should be upper cased.

The passed in string will only consist of alphabetical characters and spaces(' '). Spaces will only be present if there are multiple words. Words will be separated by a single space(' ').

Examples:

to_weird_case('String'); # => returns 'StRiNg'
to_weird_case('Weird string case') # => returns 'WeIrD StRiNg CaSe'
In [6]:
# 我的代码
def to_weird_case(string):
    return ' '.join([''.join([s[x].lower() if x % 2 == 1 else s[x].upper() for x in  range(len(s))]) for s in string.split()])

to_weird_case('String')
Out[6]:
'StRiNg'
In [ ]:
# 别人代码
def to_weird_case_word(string):
    return "".join(c.upper() if i%2 == 0 else c for i, c in enumerate(string.lower()))
    
def to_weird_case(string):
    return " ".join(to_weird_case_word(str) for str in string.split())

9. Give me a Diamond

This kata is to practice simple string output. Jamie is a programmer, and James' girlfriend. She likes diamonds, and wants a diamond string from James. Since James doesn't know how to make this happen, he needs your help.

Task:

You need to return a string that displays a diamond shape on the screen using asterisk ("*") characters. Please see provided test cases for exact output format.

The shape that will be returned from print method resembles a diamond, where the number provided as input represents the number of ’s printed on the middle line. The line above and below will be centered and will have 2 less ’s than the middle line. This reduction by 2 ’s for each line continues until a line with a single is printed at the top and bottom of the figure.

Return null if input is even number or negative (as it is not possible to print diamond with even number or negative number).

Please see provided test case(s) for examples.

Python Note
Since print is a reserved word in Python, Python students must implement the diamond(n) method instead, and return None for invalid input.

JS Note
JS students, like Python ones, must implement the diamond(n) method, and return null for invalid input.

In [35]:
# 我的代码
def diamond(n):
    if n % 2 == 0 or n < 0:
        return None
    else:
        iterlist = list(range(1,n+1,2))[:] + list(range(1,n,2))[::-1]
        return ''.join([' ' * int((n-i) / 2) + '*' * i + '\n' for i in iterlist])
        

        
print(diamond(7))
   *
  ***
 *****
*******
 *****
  ***
   *

In [ ]:
# 别人的代码
def diamond(n):
    if n > 0 and n % 2 == 1:
        diamond = ""
        for i in range(n):
            diamond += " " * abs((n/2) - i)
            diamond += "*" * (n - abs((n-1) - 2 * i))
            diamond += "\n"
        return diamond
    else:
        return None
    
def diamond(n):
    if not n%2 or n<1: return None
    d = [" "*i+"*"*(n-2*i)+"\n" for i in range(n/2,0,-1)]
    return ''.join(d) + "*"*n + "\n" + ''.join(d[::-1])

10. *The Supermarket Queue

here is a queue for the self-checkout tills at the supermarket. Your task is write a function to calculate the total time required for all the customers to check out!

The function has two input variables:

customers: an array (list in python) of positive integers representing the queue. Each integer represents a customer, and its value is the amount of time they require to check out. n: a positive integer, the number of checkout tills. The function should return an integer, the total time required.

EDIT: A lot of people have been confused in the comments. To try to prevent any more confusion:

There is only ONE queue, and
The order of the queue NEVER changes, and Assume that the front person in the queue (i.e. the first element in the array/list) proceeds to a till as soon as it becomes free. The diagram on the wiki page I linked to at the bottom of the description may be useful. So, for example:

queue_time([5,3,4], 1)
# should return 12
# because when n=1, the total time is just the sum of the times

queue_time([10,2,3,3], 2)
# should return 10
# because here n=2 and the 2nd, 3rd, and 4th people in the 
# queue finish before the 1st person has finished.

queue_time([2,3,10], 2)
# should return 12

N.B. You should assume that all the test input will be valid, as specified above. P.S. The situation in this kata can be likened to the more-computer-science-related idea of a thread pool, with relation to running multiple processes at the same time: https://en.wikipedia.org/wiki/Thread_pool

In [58]:
# 我的代码
def queue_time(customers, n = 1):
    timesum = 0
    if not customers:
        return 0
    elif n < len(customers):
        onchecking = sorted(customers[:n]) 
        for nextcustome in customers[n:]:
            timesum += onchecking[0]
            onchecking = [x-onchecking[0] for x in onchecking]
            onchecking[0] = nextcustome
            onchecking = sorted(onchecking) 
        return timesum + max(onchecking)
    else:
        return max(customers)

queue_time([1,2,3,4,5], 4)
Out[58]:
6
In [ ]:
# 别人的代码,让我觉得自己是智障
def queue_time(customers, n):
    l=[0]*n
    for i in customers:
        l[l.index(min(l))]+=i
    return max(l)

11. Playing with digits

Some numbers have funny properties. For example:

89 --> 8¹ + 9² = 89 * 1  
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2  
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51

Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:

Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k

If it is the case we will return k, if not return -1.

Note: n, p will always be given as strictly positive integers.

dig_pow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
dig_pow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
dig_pow(695, 2) should return 2 since 6² + 9³ + 5= 1390 = 695 * 2
dig_pow(46288, 3) should return 51 since 4³ + 6+ 2 + 8 + 8 = 2360688 = 46288 * 51
In [67]:
# 我的代码
def dig_pow(n, p):
    left = sum([pow(i,p+index) for index, i in enumerate([int(c) for c in str(n)])])
    return int(left / n) if left % n == 0 else -1

dig_pow(695, 2)
Out[67]:
2
In [ ]:
# 别人的代码
def dig_pow(n, p):
  s = 0
  for i,c in enumerate(str(n)):
     s += pow(int(c),p+i)
  return s/n if s%n==0 else -1

def dig_pow(n, p):
    k, fail = divmod(sum(int(d)**(p + i) for i, d in enumerate(str(n))), n)
    return -1 if fail else k

12.Persistent Bugger.

Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.

For example:

persistence(39) => 3  # Because 3*9 = 27, 2*7 = 14, 1*4=4
                       # and 4 has only one digit.
 persistence(999) => 4 # Because 9*9*9 = 729, 7*2*9 = 126,
                       # 1*2*6 = 12, and finally 1*2 = 2.
 persistence(4) => 0   # Because 4 is already a one-digit number.
 persistence(39) # returns 3, because 3*9=27, 2*7=14, 1*4=4
                 # and 4 has only one digit
 persistence(999) # returns 4, because 9*9*9=729, 7*2*9=126,
                  # 1*2*6=12, and finally 1*2=2
 persistence(4) # returns 0, because 4 is already a one-digit number
In [8]:
# 我的代码
def persistence(n):
    result = [n]
    while result[0] > 9:
        tmp = 1
        for c in str(result[0]):
            tmp *= int(c)
            
        result.insert(0,tmp)
    return len(result) - 1
 
                  
persistence(999)
Out[8]:
4
In [9]:
# 其他答案基本都用到了reduce和计数器(python2.7)
from operator import mul
def persistence(n):
    return 0 if n<10 else persistence(reduce(mul,[int(i) for i in str(n)],1))+1

import operator
def persistence(n):
    i = 0
    while n>=10:
        n=reduce(operator.mul,[int(x) for x in str(n)],1)
        i+=1
    return i

13.Weight for weight

My friend John and I are members of the "Fat to Fit Club (FFC)". John is worried because each month a list with the weights of members is published and each month he is the last on the list which means he is the heaviest.

I am the one who establishes the list so I told him: "Don't worry any more, I will modify the order of the list". It was decided to attribute a "weight" to numbers. The weight of a number will be from now on the sum of its digits.

For example 99 will have "weight" 18, 100 will have "weight" 1 so in the list 100 will come before 99. Given a string with the weights of FFC members in normal order can you give this string ordered by "weights" of these numbers?

Example:
"56 65 74 100 99 68 86 180 90" ordered by numbers weights becomes: "100 180 90 56 65 74 68 86 99"

When two numbers have the same "weight", let us class them as if they were strings and not numbers: 100 is before 180 because its "weight" (1) is less than the one of 180 (9) and 180 is before 90 since, having the same "weight" (9) it comes before as a string.

All numbers in the list are positive numbers and the list can be empty.

Notes
it may happen that the input string have leading, trailing whitespaces and more than a unique whitespace between two consecutive numbers Don't modify the input For C: The result is freed.

In [1]:
# 别人的代码,哭,我没做出来
def order_weight(strng):
    # your code
    bar = sorted(strng.split(' '))
    baz = sorted(bar, key=foo)
    return " ".join(baz)
    
    
def foo(n):
  return sum([int(item) for item in n])
   
    
string1 = "56 65 74 100 99 68 86 180 90"
order_weight(string1)
Out[1]:
'100 180 90 56 65 74 68 86 99'
In [ ]:
def order_weight(_str):
    return ' '.join(sorted(sorted(_str.split(' ')), key=lambda x: sum(int(c) for c in x)))

14. RGB To Hex Conversion

The rgb() method is incomplete. Complete the method so that passing in RGB decimal values will result in a hexadecimal representation being returned. The valid decimal values for RGB are 0 - 255. Any (r,g,b) argument values that fall out of that range should be rounded to the closest valid value.

The following are examples of expected output values:

rgb(255, 255, 255) # returns FFFFFF
rgb(255, 255, 300) # returns FFFFFF
rgb(0,0,0) # returns 000000
rgb(148, 0, 211) # returns 9400D3
In [8]:
def clamp(x): 
    return max(0, min(x, 255))


def rgb(r,g,b):
    return "{0:02X}{1:02X}{2:02X}".format(clamp(r), clamp(g), clamp(b))

rgb(255, 255, 255)
Out[8]:
'FFFFFF'
In [ ]:
# 别人的代码
def rgb(r, g, b):
    round = lambda x: min(255, max(x, 0))
    return ("{:02X}" * 3).format(round(r), round(g), round(b))

15.Duplicate Encoder

The goal of this exercise is to convert a string to a new string where each character in the new string is '(' if that character appears only once in the original string, or ')' if that character appears more than once in the original string. Ignore capitalization when determining if a character is a duplicate.

Examples:

"din" => "((("

"recede" => "()()()"

"Success" => ")())())"

"(( @" => "))(("


Notes:

Assertion messages may be unclear about what they display in some languages. If you read "...It Should encode XXX", the "XXX" is actually the expected result, not the input! (these languages are locked so that's not possible to correct it).
In [25]:
def duplicate_encode(word):
    word = word.lower()
    dict1 = dict(zip(word,[0 for i in range(len(word))]))
    result = []
    for c in word:
        if c in dict1:
            dict1[c] += 1
    for x in word:
        if dict1[x] > 1:
            result.append(')')
        else:
            result.append('(')
    return ''.join(result)
    
duplicate_encode("Success")
{'e': 0, 'u': 0, 's': 0, 'c': 0}
{'e': 1, 'u': 1, 's': 3, 'c': 2}
Out[25]:
')())())'
In [ ]:
# 别人的代码
def duplicate_encode(word):
    return "".join(["(" if word.lower().count(c) == 1 else ")" for c in word.lower()])

# 别人的代码
from collections import Counter

def duplicate_encode(word):
    word = word.lower()
    counter = Counter(word)
    return ''.join(('(' if counter[c] == 1 else ')') for c in word)

16. Maximum subarray sum

The maximum sum subarray problem consists in finding the maximum sum of a contiguous subsequence in an array or list of integers:

maxSequence([-2, 1, -3, 4, -1, 2, 1, -5, 4])
# should be 6: [4, -1, 2, 1]
Easy case is when the list is made up of only positive numbers and the maximum sum is the sum of the whole array. If the list is made up of only negative numbers, return 0 instead.

Empty list is considered to have zero greatest sum. Note that the empty list or array is also a valid sublist/subarray.
In [44]:
def maxSequence(arr):
    tmp, maxn = 0, 0
    for i in arr:
        tmp += i
        if tmp < 0:
            tmp = 0
        if tmp > maxn:
            maxn = tmp
    return maxn
    
        
maxSequence([-2, 1, -3, 4, -1, 2, 1, -5, 4])            
Out[44]:
6
In [ ]:
# 别人的实现
def maxSequence(arr):
    lowest = ans = total = 0
    for i in arr:
        total += i
        lowest = min(lowest, total)
        ans = max(ans, total - lowest)
    return ans

17. Sum by Factors

Given an array of positive or negative integers

I= [i1,..,in]

you have to produce a sorted array P of the form

[ [p, sum of all ij of I for which p is a prime factor (p positive) of ij] ...]

P will be sorted by increasing order of the prime numbers. The final result has to be given as a string in Java, C#, C, C++ and as an array of arrays in other languages.

Example:

I = [12, 15] # result = [[2, 12], [3, 27], [5, 15]]
[2, 3, 5] is the list of all prime factors(素数因子) of the elements of I, hence the result.

Notes: It can happen that a sum is 0 if some numbers are negative!

Example: I = [15, 30, -45] 5 divides 15, 30 and (-45) so 5 appears in the result, the sum of the numbers for which 5 is a factor is 0 so we have [5, 0] in the result amongst others.
In [37]:
# my solution
def sum_for_list(lst):
    prime_dict= {}
    for ii in lst:
        if valid_prime(abs(ii)):
            if prime_dict.get(abs(ii)) == None:
                prime_dict[abs(ii)] =  ii
            else:
                prime_dict[abs(ii)] = prime_dict[abs(ii)] + ii  
        for i in range(2,int((abs(ii)+2)/2)):
            if ii % i == 0 and valid_prime(i):
                if prime_dict.get(i) == None:
                    prime_dict[i] =  ii
                else:
                    prime_dict[i] = prime_dict[i] + ii  
    return sorted(dict_to_list(prime_dict))
                

def dict_to_list(prime_dict):
    res_list=[]
    for i,j in prime_dict.items():
        res_list.append([i,j])
    return res_list
        

def valid_prime(n):
    for i in range(2,int((n+2)/2)):
        if n % i == 0:
            return False
    return True
                
sum_for_list([12,15,1,107*-2,107*3])    
Out[37]:
[[1, 1], [2, -202], [3, 348], [5, 15], [107, 107]]

18. Regex Password Validation

You need to write regex that will validate a password to make sure it meets the following criteria:

At least six characters long
contains a lowercase letter
contains an uppercase letter
contains a number
Valid passwords will only be alphanumeric characters.
In [38]:
# I couldn't figure this out
# Solution 1
from re import compile, VERBOSE

regex = compile("""
^              # begin word
(?=.*?[a-z])   # at least one lowercase letter
(?=.*?[A-Z])   # at least one uppercase letter
(?=.*?[0-9])   # at least one number
[A-Za-z\d]     # only alphanumeric
{6,}           # at least 6 characters long
$              # end word
""", VERBOSE)

# Solution 2
regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^\W_]{6,}$"

Comments