<?php
function p($s){
$count = strlen($s);
$start = 0;
$end = $count-1;
$r = true;
while($start<$end){
if(!isChar($s[$start])){
$start++;
}
elseif(!isChar($s[$end])){
$end--;
}else{
if($s[$start] !== $s[$end]){
$r = false;
break;
}
$start++;
$end--;
}
}
return $r;
}
function isChar($char){
$char = strtolower($char);
if (preg_match('/[a-z]/', $char)) {
return TRUE;
}
}
print_r(p("23123123!!,,we2ew")); // return true
?>
Hi everyone,
I wrote function, that checking if string is a palindrome. String can contain any characters, digits and symbols, But I need check within a-z chars
123ebc123 - false
,<>ebbe - true
123/.~!!aaa - true
Is this most efficient way to implement this function?
p.s. don't look at the isChar function implementation, imagine there just a func that return true or false if char is letter
Thanks
If we use Big Oh notation to represent time complexity of your algorithm it will be O(n)
Related
I'm currently converting C++ code to Swift and I've gotten stuck on one part. The parameter passed into the function is a string and the area where I'm stuck is when attempting to set a variable based on the second to last character of a string to check for a certain character.
The error shows up on this line:
line[i-1]
I've tried casting this value to an Int but this didn't work:
Int(line[i - 1])
I've also tried to see if the string's startIndex function which takes a Int would work but it didn't:
line.startIndex[i - 1]
Here is the full function:
func scanStringForSpecificCharacters(line: String){
var maxOpen: Int = 0;
var minOpen: Int = 0;
minOpen = 0;
maxOpen = 0;
var i = 0
while i < line.characters.count {
for character in line.characters {
//var c: Character = line[i];
if character == "(" {
maxOpen += 1;
if i == 0 || line[i - 1] != ":" {
minOpen += 1;
}
}
else if character == ")"{
minOpen = max(0,minOpen-1);
if i == 0 || line[i-1] != ":"{
maxOpen -= 1;
}
if maxOpen < 0{
break;
}
}
}
if maxOpen >= 0 && minOpen == 0{
print("YES")
}else{
print("NO")
}
}
}
Strings in Swift aren't indexed collections and instead you can access one of four different views: characters, UTF8, UTF16, or unicodescalars.
This is because Swift supports unicode, where an individual characters may actually be composed of multiple unicode scalars.
Here's a post that really helped me wrap my head around this: https://oleb.net/blog/2016/08/swift-3-strings/
Anyway, to answer you question you'll need to create an index using index(after:), index(before:), or index(_, offsetBy:).
In your case you'd want to do something like this:
line.index(line.endIndex, offsetBy: -2) // second to last character
Also, you'll probably find it easier to iterate directly using a String.Index type rather than Int:
let line = "hello"
var i = line.startIndex
while i < line.endIndex {
print(line[i])
i = line.index(after: i)
}
// prints ->
// h
// e
// l
// l
// o
Working with Strings in Swift was changed several times during it's evolution and it doesn't look like C++ at all. You cannot subscript string to obtain individual characters, you should use index class for that. I recommend you read this article:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html
As already pointed out in the other answers, the compiler error
is caused by the problem that you cannot index a Swift String with
integers.
Another problem in your code is that you have a nested loop which is
probably not intended.
Actually I would try to avoid string indexing at all and only
enumerate the characters, if possible. In your case, you can
easily keep track of the preceding character in a separate variable:
var lastChar: Character = " " // Anything except ":"
for char in line.characters {
if char == "(" {
maxOpen += 1;
if lastChar != ":" {
minOpen += 1;
}
}
// ...
lastChar = char
}
Or, since you only need to know if the preceding character is
a colon:
var lastIsColon = false
for char in string.characters {
if char == "(" {
maxOpen += 1;
if !lastIsColon {
minOpen += 1;
}
}
// ...
lastIsColon = char == ":"
}
Another possible approach is to iterate over the string and a shifted
view of the string in parallel:
for (lastChar, char) in zip([" ".characters, line.characters].joined(), line.characters) {
// ...
}
As others have already explained, trying to index into Swift strings is a pain.
As a minimal change to your code, I would recommend that you just create an array of the characters in your line up front:
let linechars = Array(line.characters)
And then anywhere you need to index into the line, use linechars:
This:
if i == 0 || line[i-1] != ":" {
becomes:
if i == 0 || linechars[i-1] != ":" {
In Go (and G++?), the following is a common idiom:
func sqr(x int) (n int, err error) {
n = x * x
err = nil
return
}
The (n int, err error) explicitly enumerates the name and type of the return values. There are in my opinion lots of advantages to this, and I like it.
In Perl 6, we can:
my sub sqr (Int:D $x) returns Int:D {
$x ** 2;
}
The return is implicit, which makes me kind of uncomfortable (we could make it explicit with return), but you may notice the return type is specified (as is the fact it's Defined).
Unsurprisingly, there's no obvious way to return a value explicitly by name, but I'm curious, since Perl (especially 6) is extensively modifiable in every way, if there's a way to implement this.1
1 However hacky it may be, but too hacky and I'd avoid using it for "real" things.
If all else fails, you can always write your own slang.
However, here are two less involved approaches I came up with, the first one using a dynamic variable of fixed name, the second one using an rw parameter of user-defined name:
multi sub trait_mod:<is>(Routine:D \r, :$dynrv!) {
r.wrap(-> | { my $*rv; callsame; $*rv })
}
multi sub trait_mod:<is>(Routine:D \r, :$pararv!) {
r.wrap(-> |c { my $rv; callwith(|c, $rv); $rv })
}
sub double($x) is dynrv {
$*rv = $x * 2;
return 666; # discarded
}
sub triple($x, $y is rw) is pararv {
$y = $x * 3;
return 666; # discarded
}
say double 42;
say triple 42;
Note that this only supports a single return value, though I have some ideas how multiple ones could be made to work...
edit: Eg this way:
multi sub trait_mod:<is>(Routine:D \r, :#dynrv!) {
r.wrap(-> | {
my #rv = Nil xx #dynrv;
my $*rv = Map.new(#dynrv Z=> #rv);
callsame;
#dynrv > 1 ?? #rv !! #rv[0];
})
}
multi sub trait_mod:<is>(Routine:D \r, Int :$pararv!) {
r.wrap(-> |c {
my #rv = Nil xx $pararv;
callwith(|c, |#rv);
$pararv > 1 ?? #rv !! #rv[0];
})
}
sub divmod($a, $b) is dynrv<d m> {
$*rv<d> = $a div $b;
$*rv<m> = $a mod $b;
}
sub plusmin($a, $b, $p is rw, $m is rw) is pararv(2) {
$p = $a + $b;
$m = $a - $b;
}
say divmod 14, 3;
say plusmin 14, 3;
While slangs can be used to get exactly what you want, I believe they're the wrong size solution to this problem. Firstly, cat's Go example is returning error information as well as an (Int). I'd suggest the PerlĀ 6 way for that is to simply return a Fail object using &fail which the caller can test for using .defined or the // operator;
if $something_wrong {
return fail "Dang! Even the squaring function isn't working today."
}
else {
return $x ** 2
}
I know this doesn't document the dual return values as requested, but do you want to use an explicit variable for exceptional out-of-band data? What if it wasn't error data but other information?
Let's assume we want to return an (Int) with an Easter-egg message. In this case, as the extra data is a different type, (Str), we can run-time mixin a role with a .Str method that returns the message if the return value is used in string context.
return $x * $x but "Suprise! Bet you weren't expecting that!"
Alternatively, if the extra data is of the same type we can explicitly mixin an anonymous role. Let's say we want to return an (Int) with a .size property;
return $x but role { has $.size = calculate_size() }
Finally, you can document your return type explicitly by declaring the role and then using a subset to define your own (Int) type that demands the role;
role Size { has UInt:D $.size = 0 }
subset MyInt of Int where Size;
sub sqr(Int:D $x, UInt:D :$size = 12) returns MyInt:D {
return $x * $x but Size($size)
}
my $square5 = sqr(5);
say "5 squared is $square5 with size $square5.size()."
# prints: 5 squared is 25 with size 12.
Details are in S14 and S12 - Anonymous mixin roles
I want to first letter to be in upper case other in lower. But after ".", it must be upper again..
function firstToUpperCase( str ) {
return str.substr(0, 1).toUpperCase() + str.substr(1);
}
var str = 'prompt("Enter text to convert: ")
var Upcase = firstToUpperCase( str );
document.write(Upcase);
Here's a simplistic answer based on what you provided. It does not take whitespace into account following the period since you didn't mention that in the specs.
function firstToUpperCase(str) {
var parts = str.split(".");
for (i = 0; i < parts.length; i++) {
parts[i] = parts[i].substring(0, 1).toUpperCase() + parts[i].substring(1).toLowerCase();
}
return parts.join(".");
}
If you're trying to deal with sentences, something like this might be a little better, though it does not preserve exact whitespace:
function firstToUpperCase(str) {
var parts = str.split(".");
for (i = 0; i < parts.length; i++) {
sentence = parts[i].trim();
parts[i] = sentence.substring(0, 1).toUpperCase() + sentence.substring(1).toLowerCase();
}
return parts.join(". ");
Thanks for taking the time to look at my problem. What I'm trying to do is create a javascript function that tests whether a sting is a particular length and also whether each element of that string can be found in another string. The function then needs to return a boolean value of either true or false depending on whether the string is valid.
Here's what I have:
N_ALPHA = 6;
N_CHOICES = 4;
ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var alphabet = ALPHABET.substring(0, N_ALPHA);
function isValidGuess(inStr)
{ var valid;
var Str = inStr;
for (i=0; i<Str.length; i++)
{ if (Str.charAt(i) === alphabet.charAt(i) && Str.length == N_CHOICES.length)
{ valid = true;
}
else
{ valid = false;
}
}
return valid;
}
This code is not working at all. It only returns false every time. Any help you could provide would be greatly appreciated. Thank you.
N_CHOICES.length return undefined, because variable N_CHOICES is number.
you have to change your condition to
if (Str.charAt(i) === alphabet.charAt(i) && Str.length == N_CHOICES)
In a given sentence i want to split into 10 character string. The last word should not be incomplete in the string. Splitting should be done based on space or , or .
For example:
this is ram.he works at mcity.
now the substring of 10 chars is,
this is ra.
but the output should be,
this is.
Last word should not be incomplete
You can use a regular expression that checks that the character after the match is not a word character:
string input = "this is ram.he";
Match match = Regex.Match(input, #"^.{0,10}(?!\w)");
string result;
if (match.Success)
{
result = match.Value;
}
else
{
result = string.Empty;
}
Result:
this is
An alternative approach is to build the string up token by token until adding another token would exceed the character limit:
StringBuilder sb = new StringBuilder();
foreach (Match match in Regex.Matches(input, #"\w+|\W+"))
{
if (sb.Length + match.Value.Length > 10) { break; }
sb.Append(match.Value);
}
string result = sb.ToString();
Not sure if this is the sort of thing you were looking for. Note that this could be done a lot cleaner, but should get you started ... (may want to use StringBuilder instead of String).
char[] delimiterChars = { ',', '.',' ' };
string s = "this is ram.he works at mcity.";
string step1 = s.Substring(0, 10); // Get first 10 chars
string[] step2a = step1.Split(delimiterChars); // Get words
string[] step2b = s.Split(delimiterChars); // Get words
string sFinal = "";
for (int i = 0; i < step2a.Count()-1; i++) // copy count-1 words
{
if (i == 0)
{
sFinal = step2a[i];
}
else
{
sFinal = sFinal + " " + step2a[i];
}
}
// Check if last word is a complete word.
if (step2a[step2a.Count() - 1] == step2b[step2a.Count() - 1])
{
sFinal = sFinal + " " + step2b[step2a.Count() - 1] + ".";
}
else
{
sFinal = sFinal + ".";
}