[Challenge] Unique Characters in a String

challenge

#83

Thought I would add a simple PowerShell solution

$string = "unique" 
#$string = "nique" 

if($string.ToCharArray() | Group | Select Count | Where -Property Count -ne 1)
{ 
    "duplicates found" 
} 
else
{
    "all unique"
}

Convert the string to a Char array, Group(-Object) the array, Select(-Object) the Count property, Where(-Object) the Count property is not equal to 1 (the "u" has a count of 2), it means there's a duplicate!


#84

In Ruby, Arrays have a uniq method, which returns all of the elements of the array without duplicates. So the length of an array a will be the same as the length of a.uniq only if all the elements in the Array are unique.

So all I need to do is to convert the input string into an Array by using String's chars method, then compare a and a.uniq.

def challenge(str)
  if str.chars.uniq.length == str.chars.length
    puts "all unique"
  else
    puts "duplicates found"
  end
end

#85

Hello, I have tried this but it's in C so I am not eligible to anything but I don't care so that's OK.

To me this exercice is all about a two-generation iteration. We'll have to iterate through the strings, and each time we increment the variable that enables us to iterate through the string, well.. we make another iteration, with another variable. :slight_smile: Which means that in each iteration case, we have another iteration.

Here is my code:

 #include <stdio.h>
  2
  3 int main(int argc, char **argv)
  4 {
  5     int i = 0;
  6     int j = 1;
  7
  8     if (argc != 2)
  9         return (0);
 10     while (argv[1][i])
 11     {
 12         while (argv[1][j])
 13         {
 14             if (argv[1][j] == argv[1][i])
 15             {
 16                 printf("duplicates found.\n");
 17                 return (0);
 18             }
 19             j++;
 20         }
 21         i++;
 22         j = i + 1;
 23     }
 24     printf("all unique\n");
 25     return (0);
 26 }

Explanations:
the first line is a library inclusion that enables me to use the printf() function, which writes something to the screen.
argc means argument count, argv means argument value. argc is an integer, argv is an array of strings (an array of arrays).
On line 8 I verify that the number of argument is 2: the name of the executable (yes, it is an argument) + 1 string. If I have only one, it will cause my program to segfault because It will try to access memory that is not allocated for anything. If I have more than 2 arguments, which means more than 1 string to evaluate, it would work for the first string and then forget the second one. But I think that such case would be an invalid case, which means my program have to refuse to work. So if the number of argument is not 2 (the number of string is not 1), the program ends.
I think that not having 1 string with atleast 0 character is an invalid case and the program should end.
The difference between an empty string and nothing is important: if I have an empty string, it will be evaluated since it is a string. If I have nothing, nothing will be evaluated, because nothing is not a string. Nothing is not. But the program tries to access a string. That's why passing an empty string as parameter to the main function will not cause the program to segfault and passing some nothing to it will.

I use 2 iterators: j and k. They are indexes. The first one is the first character of the string evaluated, the second one is the second character of the string evaluated. If i = 3 and j = 6, the program compares the 4th character and the 7th character (providing these indexes do not correspond to the end of the string, else there is no comparison made between these two).
For each character of the string (argv[1][i]), the program checks if the following characters (argv[1][j]) are equal to it, one by one. If such condition is met, then the programs returns "duplicates found.\n" and ends. If not, it will continue iterating through the second index (j), to compare the rest of the characters to the character corresponding to argv[1][i].
At the end of the second loop, i is incremented, and j = i + 1. j must indeed be reinitialized, but if it was reinitialized to the same value than i, it would return "duplicates found" by checking if a character is equal to itself, which would be a bug in the program. We don't need to reinitialize j to 0 since it would make the program compare several combinations that were already evaluated, plus it would make the code harder and longer because we would have to skip 1 index. It's way easier and smaller and better to just make j take the value i + 1.

To end, if the program has not found any duplicates, it will get out of the loop and continue reading the main function. Such case means that there was no duplicate found. Before the ending return (0), it displays "all unique\n", because all characters are unique.

Here is a screenshot of how it works:
how it works
Notice that the "comparing ..." lines are not in the code above. I only added some printf() int it, so we can see what happens when the program runs, but that does not change anything concerning it's performance.


#86

In Python my first thought was to compare the length of the string to the length of the set() of the string. Since set() returns all the unique characters in the string very efficiently, this is a very fast comparison.

def check_unique(new_string):
    if len(set(new_string)) == len(new_string):
        return("all unique.")
    else:
        return("duplicates found")

#check if a string is unique
print(check_unique(new_string))

For the extra credit challenge of not using any other data structures, like set(), I decided to iterate through the string, looking to see if the current character is repeated in the subsequent characters, and return out of the function if it finds a duplicate. That way you don't waste time iterating after you've already found a duplicate. Using enumerate() seems to be the most efficient way to do this.

def check_unique(new_string):
    for idx, letter in enumerate(new_string):
        if letter in new_string[idx+1:]:
            return("duplicates found")

    return("all unique")

#check if a string is unique
print(check_unique(new_string))

#87

def isAllUnique(s):
 uniqueCharsInS = set(s)
 return len(uniqueCharsInS) == len(s)

def printUniqueness(s):
 if isAllUnique(s): print("No Duplicates Found.")
 else: print ("Duplicates Found.")

I split this into two Python functions because the one that returns the boolean value might be repurposed later, when other things than printing the output need to be done with this.

The core function works by converting the string (a list of characters) to a set - this conveniently drops all duplicate items. I then compare the length of the resulting set to the length of the original to check whether elements have been dropped in the conversion.

This solution is very short but does create a new set.

Note this works on any list object (not just strings). It does not check whether the argument is a string, or whether it contains only alphanumeric characters. It does not see lower and uppercase letters as duplicates of the same character. If such constraints were needed, I would add a line like

def isAllUnique(s):
 sAlpha = [c.lower() for c in s if c.isalpha()]
 charsInS = set(sAlpha)
 return len(charsInS) == len(sAlpha)

This checks only the alphabetical characters in the input against each other and matches lowercase letters with uppercase letters. So, for example, 'Ee' is 'duplicates found', '2787667jusw' is 'all unique'.


#88

My solution in JS.
Step 1) split input string into array
Step 2) sort the array
Step 3) Go through the array, if two consecutive cells have same value -> duplicate character

function hasDuplicates(inputString)
{
    var searchSpace = inputString.split("").sort();
    for (var n = 0, end = searchSpace.length - 1; n <= end ; n++)
    {
        if (searchSpace[n] === searchSpace[n+1])
            return true;
    }
    return false;
}

var input = prompt("Give me a string");
alert(hasDuplicates(input) ? "Duplicates found " : "All unique");

#89

I'm not too sure about your reasoning about Python being the best language for this but my solution is in Javascript anyway!

The logic behind the function is as follows:
1. Turn the string into an array. This gives us a list of chars to loop around and a bunch of methods we can therefore use.
2. Run a filter pass over the characters in the array. Return each character if it passes the filter test. The test looks for the character index in the array. If the string is made up of unique characters, there should only be one index and it will be the correct one. If the character appears more than once in the string, the index returned will differ.
3. The outcome is for duplicate chars - the filter pass will return a different string to the original. Hence we should simply compare the length of the original string to the string returned from the filter pass.
4. Finally we turn the array back into a string and do a simple ternary expression on it.

I like this solution because it used the filter function ie. a solid piece of functionality of the array of chars. In a sense the array is testing itself !!

If I was to do this again, I would write the function so that I would abandon it the moment I found a duplicate as the string could be very long - this would be a more sensible (productionised) way of doing it.

function checkUniqueCharacters(str){
   return str.split('').filter(function(ch, idx, arr){ 
      return arr.indexOf(ch) === idx; 
   })
   .join('').length !== str.length 
   ? "duplicates found" 
   : "all unique";
}

checkUniqueCharacters("abcdefgcj"); // Returns duplicates found
checkUniqueCharacters("abcdefgj"); // Returns all unique

#90

This is my first coding challenge and the first time am coding in Python. Thx for this challenge.

My tought is to use a counter to count duplicate elements in the passed string and break the loop if one duplicate element is found, then I print a message wether it has a duplicate element or not.
I check if the str is not empty or is not made only with spaces.
I also put the passed string into a lower case to avoid case sensitive problem, Python is case sensitive.
Hope this is simple and elegant !!
Regards :slight_smile:

def hasDuplicate( str ):
    "This prints if a passed string into this function has all unique caracters or not"
    if len(str)>0 and not str.isspace() :
        duplicate= False 
        str= str.lower()
        for letter in str :
            n= str.count(letter)
            if n>1 : 
                duplicate = True
                break
            elif n==1 :
                continue
        if duplicate:
            print "duplicates found"
        else:
            print "all unique"
    return

#91

Here's a way to do it in BASH if anyone is interested:

dupes () {
newlines=$(echo -n $string | sed 's/./&\n/g')
online=$(echo "$newlines"|sort|uniq -c|awk '{print $1}'|egrep '[2-9]|[1-9][0-9]')
if [[ $online -ne "" ]]; then echo "duplicates found";else echo "all unique";fi
}

Line 1 is basically declaring the function
Line 2 is taking the variable "$string" and splitting it up to a new line per character and assigning it to a new variable ($online)
Line 3 does the bulk of the check, it sorts the $online variable into alphabetic order (using sort), then it counts the unique characters and outputs that count into column 1 (using uniq), then outputs only the 1st column (the count values using awk), then it searches each line for any value greater than 1 and outputs only those lines (using grep).
This leaves us with either an empty output (the count of each unique character would be "1"), or it there is a value of greater-than-1 indicating that there are duplicates.
Line 4 Is a simple IF statement that checks if the output from line 3 is empty and then outputs the required "all unique", or if it is not empty outputs the "duplicates found" line.
Line 5 is just closing off the function.


#92

Hi All,

I'm sure there are more efficient ways to do this but here my Python 2.7 based solution to the challenge.
I created I counter that looping throught the letters of the script counts how many times the letter appears.

  • The script is divided in two parts, one from index 0 to the letter position and one from the letter position to the end of the script.

  • If the letter is found in one of the two groups (that exclude the position of the letter object of the iteration) than the counter is augmented by one unit.

  • If no duplicates are found the counter final value must be 0!

def find_doubles(script):
  script = script.lower()
  a = 0
  for letter in script:
    if letter in script[0:(script.index(letter))]:
      a += 1
    elif letter in script[(script.index(letter)+1):len(script)]:
      a += 1
  if a > 0:
    print "duplicates found"
  else:
    print "all unique"

#93

I came up with three different solutions, presented in Python 3.

First I tried the most obvious solution: Memorize all seen characters and fire False whenever you encounter the same character again.

Problem: Additional list do administer.

Next solution: Just split the string in all its characters and remove duplicates. set() is doing this for us, and so in the end it comes down to compare the length of the original string with the set of unique characters.

Problem: Highly abstract method set is doing all the job and an additional data structure

Next solution: Dont use any additional variables or data structures. Only work with the string presented: So I solved the task by a look forward search: Take the current character and look through the rest of the string if this character is used again. Simple and neat.

Problem: Still not feeling as the best solution, because we have to iterate every character AND for each character over the rest of the string. Maybe we can break it down to only one operation per character? Yes

Final Solution: Try to find out how many characters are there by simple cutting it out. So we replace character c with '' and compare the length of before and after. This tells us exactly when there is a duplicate.

An alternative to the last approach is to sort the string and just compare two directly following characters. But you have the cost for sorting.

Programmed with a static helper class and some test cases. Just replace method1 with method2 or method3 in the isUnique() method. Or even better, use all 3 of them and compare results.

However, very much is unclear in this challenge, therefore I did not assume anything unstated:

  • What about case sensitivity? Is "a" a duplicate of "A"?
  • What about special characters like punctuation?
  • What about whitespace? Is "what a nice day" the same as "Whataniceday"?

Though it would be easy to treat each of these, it was not stated and so it was not covered in my solution.

class stringTester:

  @staticmethod
  def method1(s):
    tmpLetters = []
    for c in s:
      if not c in tmpLetters:
        tmpLetters.append(c)
      else:
        return False

    return True

  @staticmethod
  def method2(s):
    if (len(s) == len(set(s))):
      return True
    else:
      return False

  @staticmethod
  def method3(s):
    for i, c in enumerate(s):
      if s.count(c, i+1) > 0:
        #print("Test for {0} in {1}".format(c, s[i+1:]))
        return False

    return True

  @staticmethod
  def method4(s):
    for c in s:
      if (len(s.replace(c, '')) != len(s) -1):
        return False

    return True

  @staticmethod
  def isUnique(s):
    # should be all true or all false
    results = [
      stringTester.method1(s),
      stringTester.method2(s),
      stringTester.method3(s),
      stringTester.method4(s)
    ]

    assert(all(results) or not any(results))

    if all(results):
      return "all unique"
    else:
      return "duplicates found"


def test():
  testStrings = [
    ("we are all lost!", "duplicates found"),
    ("What nice cloud", "duplicates found"),
    ("abcdefghijklmnopqrstuvwxyzß", "all unique"),
    ("Someday I come for you", "duplicates found"),
    ("IDUnique", "all unique"),
    ("ABJDjk", "all unique"),
    ("ABC", "all unique"),
    ("Whatnicedog", "all unique"),
    (".,-!?()=[]&%$§", "all unique"),
    ("42", "all unique"),
    ("population", "duplicates found"),
    ("ABCabc", "all unique")
  ]

  for s,t in testStrings:
    assert(stringTester.isUnique(s) == t)

test()

#94

In my Python code, I initially defined "string" as the string the user needs to input for it to be analysed by the code. I set a state to True, and finally defined an empty list "characters". The string was made sure to be converted to all lowercase letters so that the code would not distinguish an uppercase latter from a lowercase letter of the same kind as two different characters.
I then start a for loop which takes each character in the string and appends it to the "characters" list. The loop checks if a character is in the list already: if it isn't, it goes on and appends the new character. If it is, the loop breaks and the state is changed to False.
At the end, depending on whether the state has stayed True (i.e. no duplicates are found) or if it has been changed to False, it is printed whether the string contained duplicates or not.

string = raw_input("Write here the string you want to analyse:\n")
state = True
characters = []
string = string.lower

for i in string:
	if i not in characters:
		characters.append(i)
	elif i in characters:
		state = False
		break
		
if state == True:
	print "all unique"

if state == False:
	print "duplicates found"

#95

So, this is my first thought solution in PHP. It isn't super efficient or simple, but it works.
The first idea that came to my mind when I saw the challenge was to work with the string as an array and iterate through it with a double loop schema, and inside the second loop compare the two letters. While testing my solution, I realised that it would give a false positive for when a letter is Uppercase and the other is Lowercase, and therefore decided to convert the whole string to uppercase before iterating through it.

   <?php
        $stringGiven = "Strings";
        $repeats = false;
        $stringGiven = strtoupper($stringGiven);

        for($i = 0; $i < strlen($stringGiven) - 1; $i++){
            for($j = ($i + 1); $j < strlen($stringGiven); $j++){
                if($stringGiven[$i] == $stringGiven[$j]){
                    $repeats = true;
                    $i = strlen($stringGiven);
                    break;
                }
            }
        }

        if($repeats == true){
            echo 'Duplicates found';
        }
        else{
            echo 'All Unique';
        }
    ?>

#96

Hi,
I do not know Python, but I did study some JavaScript.

I had the idea that this could be done by 'eating up' the string with the method String.prototype.slice(a,b).

Kind of like eating a snack bar: you take a bite and compare that to the rest of the snack bar. Comparision with the method String.prototype.indexOf().

If you take the char's positions for a string with the lengh of 5 chars, it would look like this:
[0] 1 2 3 4
0 / [1] 2 3 4
0 1 / [2] 3 4
0 1 2 / [ 3] 4
...

This is the code for my solution in JavaScript:

var testString = 'abcdefghjkl12346789';
var isUnique = true;
var chopString = testString;

while( 1 < chopString.length ){	//run as long as the string has 2 or more chars
	var firstChar = chopString[0]; //getting the 1st char
	chopString = chopString.slice(1, chopString.length); //removing the 1st char
	if (chopString.indexOf(firstChar) > -1){  //comparing the 1st char against the rest
		isUnique = false;
		break;
	}
}

if (isUnique) {
	console.log('all unique');
} else {
	console.log('duplicates found');
}

#97

Here's my ruby solution! Uses array uniq method.

# Prints "all unique" if the input string is unique, otherwise print "duplicates found"
def unique? (input_string)
   raise ArgumentError.new("Input must be a string") unless input_string.is_a? String
   puts unique_string?(input_string) ? "all unique" : "duplicates found"
end

# Return true if the string is made up of unique characters, otherwise return false
def unique_string? (input_string)
    input_string.chars.to_a == input_string.chars.to_a.uniq
end

#98
  • charList table is filled all printable ASCII characters
  • countList list is created with all elements as zero and the length is equal to to the length of the printable ASCII characters list
  • Input is received by the user
  • First for loop, loops on the string elements and increases the corresponding index number in the countList by 1.
  • Second for loop, loops on the countList, if any element is above 1, breaks out of the loop and returns the result as duplicates
  • In the end, if any of the elements are 1 and 0, it returns the result as unique.

def DuplicateChecker():

    import string

    charList = string.printable
    countList = [0] * len(charList)
    userInput = input("Please put in a string for the function to check: ")
    result = "all unique"

    for character in userInput:
        charIndex = charList.index(character)
        countList[charIndex] += 1

    for counter in countList:
        if counter > 1:
            result = "duplicates found"
            break

    return print(result)

#99

  let dups = false;

  for (let x in this) {
    if (this[this[x]]) {
      dups = true;
    } else {
      this[this[x]] = 1;
    }
  }
  
  return dups;
}

console.log('truck'.duplicates()); //false
console.log('building'.duplicates()); //true

#100

Here's my effort in node, only thought process is to keep it simple i.e. easy enough for me to understand! :slight_smile:

const isUnique = (value) => {
    const lowerArray = value.toLowerCase().split('');
    return !lowerArray.some((element) => isCharRepeated(lowerArray, element), this);
};

const isCharRepeated = (stringArray, character) => {
    let characterCount = 0;
    return stringArray.some((element) => {
        if (element === character) characterCount++;
        return characterCount > 1;
    });
}

#101

In JavaScript:
For each char in the string, I need to determine if that char is present anywhere else in the string.
I can use the indexOf method of the string class to determine this. IndexOf returns -1 if the char is not present anywhere in the string, which when the full string is scanned will never be true. So at first I could check if the char is present anywhere before the current char, then I can check wether the char is repeated anywhere after the current char, by using the 'start' parameter to the indexOf method. But if I find a duplicate of the string, I'll end the loop, so I scan skip the first part, because the loop will aready have exited earlier, when the char was found after the current char.

		
		function allUniqueChars( str ) {
			/* For each char in the str check if this char is present anywhere after current pos in the same str */
			var pos = 0;
			while( pos<str.length) {
			  if (str.indexOf(str[pos],(pos+1))>pos++) {
    			return false;
			  }
		  }
		  return true;
		}

#102

<html>
<head>
<title>Code Accademy String Duplicate challenge by Kasio99 - www.kasio99.com</title>
<script>
function checkDuplicate(){
	//get the string from the input
	var string = document.getElementById('string').value;
	//split the characters into an array
	var string = string.split("");
	//create another array sorting all the character, in theory all duplicates should be sitting side by side
	var sorted_string = string.slice().sort();
	//creat the success/fail variable that will be changed if a duplicate is found
	var result = "all unique";
	//A for loop that will run through all the values of the array and check if it equals the value next to it.
	for (var i = 0; i < string.length - 1; i++) {
		if (sorted_string[i+1] == sorted_string[i]) {
			//if the function finds a duplicate, update the success/fail variable
			var result = "duplicates found";
		}
	}
	//alert the result
	alert(result);
}

</script>
</head>
<body>
<input type="text" size="40" id="string">
<button style="width: 100px;" onclick="checkDuplicate()">Go!</button>
</body>
</html>