27

I want to write a program that would take a string, let's say "Fox", then it would display:

fox, Fox, fOx, foX, FOx, FoX, fOX, FOX

My code so far:

string = raw_input("Enter String: ")
length = len(string)
for i in range(0, length):
    for j in range(0, length):
        if i == j:
            x = string.replace(string[i], string[i].upper())
            print x

Output so far:

Enter String: fox
Fox
fOx
foX
>>> 
Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
Whiskey
  • 449
  • 1
  • 7
  • 14
  • 2
    Are you allowed to use library functions for this? – georg Jun 21 '12 at 18:25
  • 2
    @thg: He didn't say it was homework, so obviously he wants the most elegant solution (which will probably involve `itertools` ;) – Niklas B. Jun 21 '12 at 18:27
  • I actually looked throu the itertools model..but that gives a permutation, which i saw in other post of stackoverflow... but what i need here is to have the out put with all possible upper case and lower case combinations. – Whiskey Jun 21 '12 at 18:28
  • 1
    This question is pretty much a duplicate of: http://stackoverflow.com/questions/6792803/finding-all-possible-case-permutations-in-python However, the answer here is much better than the answer to that other one, so I'm glad this question was asked! `itertools` for the win. – steveha Jun 23 '12 at 00:14
  • Does this answer your question? [Finding all possible case permutations in Python](https://stackoverflow.com/questions/6792803/finding-all-possible-case-permutations-in-python) – iacob Mar 27 '21 at 12:43

7 Answers7

54
import itertools

s = 'Fox'
map(''.join, itertools.product(*zip(s.upper(), s.lower())))
>>> ['FOX', 'FOx', 'FoX', 'Fox', 'fOX', 'fOx', 'foX', 'fox']
iacob
  • 20,084
  • 6
  • 92
  • 119
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • This is nice too..simple solution.. Thanks Everyone :) – Whiskey Jun 21 '12 at 18:37
  • @NiklasB. Maybe, but that doesn't make this any easier to read for anyone not well-versed in what each element does. – Marcin Jun 21 '12 at 18:41
  • 1
    @Marcin: Feel free to add an explanation. However, I doubt that it will contain any more enlightening information than what the documentations of the functions involved already contain. – Niklas B. Jun 21 '12 at 18:42
  • 6
    @Marcin: No, as you might know, I often answer Python questions and if I feel that it's necessary, I also add useful explanations. So far, nobody complained. Typically what the people need is the necessary tools. By providing a one-liner like in this excellent answer, people can then learn how the tools can be used to achieve the goal by examining what the solution does. The research they need to do to comprehend a solution is a very nice learning experience. Of course they can always come back and ask for an explanation if they don't understand something. – Niklas B. Jun 21 '12 at 18:44
  • @NiklasB. Stackoverflow is supposed to be a place for information, not a place for lessons and puzzles. – Marcin Jun 21 '12 at 18:48
  • 3
    @Marcin: I don't agree. For people like me who typically answer questions, it's gotta be fun. For people learning a new programming language, it's gotta be fun and educational. I feel that exploring new language constructs is a lot of fun, so I sometimes don't want to spoil that experience. But that's only my personal opinion and approach to SO, I'm fine with other people not feeling the same. Again, SO is collaborative, so you should add an explanation if you feel one is necessary. – Niklas B. Jun 21 '12 at 18:50
8

I always wanted to try this.

No idea if this fits your qualifications(it does work though).

str = raw_input()

def getBit(num, bit):
   return (num & 1 << bit) != 0

for i in xrange(0,2**len(str)):
   out = ""
   for bit in xrange(0,len(str)):
      if getBit(i,bit):
         out += str[bit].upper()
      else:
         out += str[bit].lower()

   print(out)

The idea is that as you increment in binary, you get every possible permutation of 1s and 0s.

Then you simply convert this list of 1s and 0s to a string, 1 meaning uppercase, 0 meaning lowercase.

5

This is the excellent, accepted answer by @ephemient modified a little bit.

Changes:

  • lower-case before upper-case, just so the list starts with "fox" instead of "FOX" (the question's example sequence starts with "fox")

  • use of a list comprehension instead of map() (either way is fine, really)

  • broke out the code that generates the lower/upper case pairs to make it more clear

  • packaged it up into a function.

The code:

import itertools as it

def cap_permutations(s):
    lu_sequence = ((c.lower(), c.upper()) for c in s)
    return [''.join(x) for x in it.product(*lu_sequence)]
steveha
  • 74,789
  • 21
  • 92
  • 117
2

One liner using list comprehension:

from itertools import permutations

strs='fox'
combin=[''.join(x) for x in permutations(list(strs)+list(strs.upper()),3) if ''.join(x).lower()=='fox']
print(combin)
>>> ['fox', 'foX', 'fOx', 'fOX', 'Fox', 'FoX', 'FOx', 'FOX']

Using a for loop:

from itertools import permutations

strs='fox'
lis2=list(strs)+list(strs.upper())

for x in permutations(lis2,3):
    if ''.join(x).lower()=='fox':
        print(''.join(x))

>>> fox
    foX
    fOx
    fOX
    Fox
    FoX
    FOx
    FOX
iacob
  • 20,084
  • 6
  • 92
  • 119
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

Use product (False, True) to find any permutations of change char in string for upper & lower:

def capitalize_char_permutation (string:str) -> str :
    conditions = product((0,1), repeat=len(string))
    for i in conditions:
        result = ''
        for j in range(len(i)):
            if i[j]==0 :
                result+= string[j].lower()
            else:
                result+= string[j].upper()
        yield result
iacob
  • 20,084
  • 6
  • 92
  • 119
1

I combined @ephemient's solution, @steveha's solution, and my own tweak.

def allcasecombinations(s):
    return list({''.join(x) for x in itertools.product(*zip(s.upper(), s.lower()))})

my improvement is using a set and then converting it to a list. the set is to remove duplicates: for example if your string had punctuation, the original function would have duplicates (because " ".upper() == " ".lower()). I incorporated @steveha's work cause I figured using list comprehension inside a set is cleaner than list(set(map(itertoolsmagic))). the list conversion probably isn't necessary for most use cases, but I added it to be safe.

>>> allcasecombinations("hi!")
['HI!', 'hI!', 'Hi!', 'hi!']
reticivis
  • 489
  • 2
  • 7
  • 13
0

Although what I tried is in c++, I guess you will get the logic. I was stuck in the same question so I searched around and this is what I ended up writing...I know it is not perfect and I would love if someone helps me make this code better and point out my mistakes.

#include <bits/stdc++.h>

using namespace std;

string decToBinary(int n,int l) 
{ 
    string ret="";
    for (int i = l-1; i >= 0; i--) { 
        int k = n >> i; 
        if (k & 1) 
            ret=ret+"1"; 
        else
            ret=ret+"0";
    }
    return ret; 
}

int main()
{
    string x;
    cin>>x;
    transform(x.begin(), x.end(), x.begin(), ::tolower); 
    int size=x.length();
    string bin;
    for(int i=0;i<pow(2,size);i++)
    {
        bin=decToBinary(i,size);
        for(int j=0;j<size;j++)
        {
            if(bin[j]=='1')
                cout<<(char)(x[j]-32);
            else
                cout<<x[j];
        }
        cout<<endl;
    }
}

Suppose the word "dog"...so, there will be 2^(number of letters) i.e. 2^3=8 combination. So, in this program, we iterate from 0-7 and convert the iterator(i in this case) to binary, for example, take the fifth iteration the binary would be 101 then the resultant word would be DoG (taking 1 as upper case and 0 as the lower case)..like this you can get all 2^n resultant words.

Max
  • 11
  • 1