-2

I need to get an array of all possible cases of a string. Like it's written here:

Combination of all possible cases of a string

How do I do that in Perl efficiently?

I want something like this:

print "$_\n" for GetCases('perl');

# Output:
perl
Perl
...
pERl
...
PERL

Note

I tagged glob because it's the function to which I want to feed the result, so people as me will later find the question. However, The question is not only about this particular case of usage.

Related question : Should I insert some code when asking for idea?

Community
  • 1
  • 1
theoden8
  • 773
  • 7
  • 16
  • 2
    Great. What are you having trouble with? – fugu Jul 17 '15 at 10:59
  • @fugu, actually, I need case-insensitive `glob` to find all files in folders with no matter to cases. As I couldn't get glob working case-insensitively, I thought that feeding it all possible cases of a string is the best way out. To my mind, there's no better language that **Perl** to cope with such things, but I don't know how to do it without monkeycode. – theoden8 Jul 17 '15 at 11:03
  • Offering a sample of what you tried is usually a route to better answers. Because in that case - there's a better answer. Have a look here and look for `:nocase` : http://perldoc.perl.org/File/Glob.html – Sobrique Jul 17 '15 at 11:26
  • @Sobrique, doesn't it distract people who want to be the first from the point? – theoden8 Jul 17 '15 at 11:28
  • 3
    Well, no, not really. Stack Overflow is about helping people fixing coding problems. It's a lot easier to do this if we can see the code that we're fixing. Or indeed - an example of what they're _actually_ trying to do, because by doing so you get a better idea of an appropriate answer. Your question above looks a lot like an XY problem now, because the problem you're trying to solve is a case insensitive glob. Which is a lot easier. – Sobrique Jul 17 '15 at 11:30
  • @Sobrique, okay, I'll try to edit the answer. – theoden8 Jul 17 '15 at 11:32
  • 1
    ***"doesn't it distract people who want to be the first from the point"*** Does this mean what I think it means -- that you imagine a race amongst contributors to get the first answer in and thereby score points, and an example of what you have tried may slow such people down? While there may be people like that, the best posters just try to write the best answer that they can – Borodin Jul 17 '15 at 11:55
  • 1
    @Borodin, I don't think this means what you think it means. There are several ways to quicker get [reputation](http://meta.stackexchange.com/questions/17204/six-simple-tips-to-get-reputation-fast-on-any-stack-exchange-site). Sometimes people make a raw answer and then polish it. There's nothing more that it means. – theoden8 Jul 17 '15 at 12:16
  • 1
    @Borodin, exactly what is told in a comment above. People have different aims and needs on stackexchange. One of the ways of asking my as little as 65-rep practice says is that if your question isn't as clear as two words, you gonna get a disambiguation in answers, partially because people are in a hurry, partially because they are too lazy to understand what you want. As it can be seen in my [first question](http://stackoverflow.com/questions/29783196/stdcerr-cant-print-float-variable), too much code makes it too complicated and unclear. – theoden8 Jul 17 '15 at 12:41
  • @Borodin, I tried to do what you said. Is it more comprehensible now? – theoden8 Jul 17 '15 at 13:02
  • @theoden: Yes, it's clear. But it still doesn't look like you've made any effort to find or write your own solution – Borodin Jul 17 '15 at 13:22
  • @Borodin, before I write anything, the more strict the language, the more exactly I must know what I want to achieve. In this question I'm asking what should I achieve : what are the ways of doing it. That's at least what I think I asked. Perhaps, it sounded a bit rude and stupid. This time. – theoden8 Jul 17 '15 at 13:32
  • @theoden: If that's what you're asking then it's *off topic* for Stack Overflow – Borodin Jul 17 '15 at 14:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83557/discussion-between-theoden-and-borodin). – theoden8 Jul 17 '15 at 14:04

2 Answers2

3

If you're aiming to use if for glob anyway then you can use glob's built-in pattern generation

my $filename = 'File.CSV';

my $test = $filename =~ s/([a-z])/sprintf '{%s,%s}', uc($1), lc($1)/iegr;

say $test, "\n";
say for glob $test;

output

{F,f}{I,i}{L,l}{E,e}.{C,c}{S,s}{V,v}

FILE.CSV
FILE.CSv
FILE.CsV
FILE.Csv
FILE.cSV
FILE.cSv
FILE.csV
FILE.csv
FILe.CSV
FILe.CSv
FILe.CsV
FILe.Csv
FILe.cSV
FILe.cSv
FILe.csV
FILe.csv
FIlE.CSV
FIlE.CSv
FIlE.CsV
FIlE.Csv
FIlE.cSV
FIlE.cSv
FIlE.csV
FIlE.csv
FIle.CSV
FIle.CSv
FIle.CsV
FIle.Csv
FIle.cSV
FIle.cSv
FIle.csV
FIle.csv
FiLE.CSV
FiLE.CSv
FiLE.CsV
FiLE.Csv
FiLE.cSV
FiLE.cSv
FiLE.csV
FiLE.csv
FiLe.CSV
FiLe.CSv
FiLe.CsV
FiLe.Csv
FiLe.cSV
FiLe.cSv
FiLe.csV
FiLe.csv
FilE.CSV
FilE.CSv
FilE.CsV
FilE.Csv
FilE.cSV
FilE.cSv
FilE.csV
FilE.csv
File.CSV
File.CSv
File.CsV
File.Csv
File.cSV
File.cSv
File.csV
File.csv
fILE.CSV
fILE.CSv
fILE.CsV
fILE.Csv
fILE.cSV
fILE.cSv
fILE.csV
fILE.csv
fILe.CSV
fILe.CSv
fILe.CsV
fILe.Csv
fILe.cSV
fILe.cSv
fILe.csV
fILe.csv
fIlE.CSV
fIlE.CSv
fIlE.CsV
fIlE.Csv
fIlE.cSV
fIlE.cSv
fIlE.csV
fIlE.csv
fIle.CSV
fIle.CSv
fIle.CsV
fIle.Csv
fIle.cSV
fIle.cSv
fIle.csV
fIle.csv
fiLE.CSV
fiLE.CSv
fiLE.CsV
fiLE.Csv
fiLE.cSV
fiLE.cSv
fiLE.csV
fiLE.csv
fiLe.CSV
fiLe.CSv
fiLe.CsV
fiLe.Csv
fiLe.cSV
fiLe.cSv
fiLe.csV
fiLe.csv
filE.CSV
filE.CSv
filE.CsV
filE.Csv
filE.cSV
filE.cSv
filE.csV
filE.csv
file.CSV
file.CSv
file.CsV
file.Csv
file.cSV
file.cSv
file.csV
file.csv
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Thanks, that's what I was aiming to get. However, I wrote **Note** especially to get the answer about getting all cases. Could you, please, slightly edit the answer, so it fully answers the question? – theoden8 Jul 17 '15 at 11:15
  • @theoden: How does it not fully-answer the question? – Borodin Jul 17 '15 at 11:48
  • It shows how you use `glob`. I was asking for getting all cases. It's not any kind of making it strict, it just misunderstanding the question: What I was interested in is how to create a list of cases for general purpose, and mentioned a task where I faced such problem. But I've given upvote for good and useful code you provided. – theoden8 Jul 17 '15 at 11:54
  • Thank you, but just because I happen to use `glob` doesn't mean the code searches for files. As you see in my answer, it simply generates all mixed-case strings as you asked. Try it yourself, and try different values for `$filename` -- those names don't have to exist – Borodin Jul 17 '15 at 11:58
1

I'd be thinking in terms of:

  • Loop through the number of possibilities. (2^length).
  • Print the 'count' in binary, because that gives a bit mask.
  • Use that bit mask to flip the bits on each iteration.

Something like this:

#!/usr/bin/env perl

use strict;
use warnings;

my $string = "abcde";

for my $mask ( 0 .. 2**length($string) - 1 ) {
    my @bits = split( '', sprintf( "%0" . length($string) . "b\n", $mask ) );

    for ( split( '', $string ) ) {
        if ( shift @bits ) {tr/a-z/A-Z/}
        print;
    }
    print "\n";
}

This works on pure alphabetical strings to the transformations, but it will always generated 2^length strings, and any character that isn't alphabetic will create duplicates.

'abcdef' will generate case variants to 'abcdeF, abcdEf, abcdEF...ABCDEF'. However '12345678' will generate 256 identical strings.

The easiest way of dealing with that case if it's problematic is to use a hash of strings rather than an array, and use keys to extract the uniques.

However, as you note in your comments:

I need case-insensitive glob to find all files in folders with no matter to cases. As I couldn't get glob working case-insensitively, I thought that feeding it all possible cases of a string is the best way out. To my mind, there's no better language that Perl to cope with such things, but I don't know how to do it without monkeycode.

What you want is to be looking at File::Glob - specifically the :nocase parameter.

Sobrique
  • 52,974
  • 7
  • 60
  • 101
  • This will produce a lot of duplicates where there are non-alphabetic characters in the target string – Borodin Jul 17 '15 at 11:52
  • Yes, this is true. The original referenced question is about a 'normal' alpha string though, and generates pretty much the same way, which is why I did it this way. – Sobrique Jul 17 '15 at 11:54
  • Peace, it's just about filenames. I was writing a simple program to quickly access my conspects. However, @Borodin, could you please give a cleaner solution? – theoden8 Jul 17 '15 at 11:58
  • It's far from clear from the question what strings the OP will be processing. I think you should at least point out that a string like `12345678` will produce 256 copies of `12345678` – Borodin Jul 17 '15 at 12:01
  • The referenced post says: "I want a program to generate: Abcdefghij ABcdef.. . . aBcdef.. . ABCDEFGHIJ" which was what I was going on. However I shall amend to make explicit. – Sobrique Jul 17 '15 at 12:04